Bagaimana sebuah WPF UserControl mewarisi WPF UserControl?

95

WPF UserControl berikut disebut DataTypeWholeNumber yang berfungsi.

Sekarang saya ingin membuat UserControl yang disebut DataTypeDateTime dan DataTypeEmail , dll.

Banyak Properti Ketergantungan akan dibagi oleh semua kontrol ini dan oleh karena itu saya ingin meletakkan metode umum mereka ke dalam TipeData dan masing-masing KontrolPengguna ini diwarisi dari tipe dasar ini.

Namun, ketika saya melakukan itu, saya mendapatkan kesalahan: Deklarasi Parsial mungkin tidak memiliki kelas dasar yang berbeda .

Jadi bagaimana saya dapat mengimplementasikan warisan dengan UserControls sehingga fungsionalitas bersama semuanya ada di kelas dasar?

using System.Windows;
using System.Windows.Controls;

namespace TestDependencyProperty827.DataTypes
{
    public partial class DataTypeWholeNumber : BaseDataType
    {
        public DataTypeWholeNumber()
        {
            InitializeComponent();
            DataContext = this;

            //defaults
            TheWidth = 200;
        }

        public string TheLabel
        {
            get
            {
                return (string)GetValue(TheLabelProperty);
            }
            set
            {
                SetValue(TheLabelProperty, value);
            }
        }

        public static readonly DependencyProperty TheLabelProperty =
            DependencyProperty.Register("TheLabel", typeof(string), typeof(BaseDataType),
            new FrameworkPropertyMetadata());


        public string TheContent
        {
            get
            {
                return (string)GetValue(TheContentProperty);
            }
            set
            {
                SetValue(TheContentProperty, value);
            }
        }

        public static readonly DependencyProperty TheContentProperty =
            DependencyProperty.Register("TheContent", typeof(string), typeof(BaseDataType),
            new FrameworkPropertyMetadata());


        public int TheWidth
        {
            get
            {
                return (int)GetValue(TheWidthProperty);
            }
            set
            {
                SetValue(TheWidthProperty, value);
            }
        }

        public static readonly DependencyProperty TheWidthProperty =
            DependencyProperty.Register("TheWidth", typeof(int), typeof(DataTypeWholeNumber),
            new FrameworkPropertyMetadata());



    }
}
Edward Tanguay
sumber
untuk solusi WPF dengan warisan Visual lihat: svetoslavsavov.blogspot.gr/2009/09/… atau untuk secara eksplisit mendefinisikan GUI pada leluhur lihat support.microsoft.com/kb/957231
George Birbilis

Jawaban:

132

Pastikan Anda telah mengubah tag pertama di xaml untuk juga mewarisi dari jenis dasar baru Anda

Begitu

<UserControl x:Class="TestDependencyProperty827.DataTypes.DataTypeWholeNumber"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        
    xmlns:s="clr-namespace:System;assembly=mscorlib"
    >

menjadi

<myTypes:BaseDataType x:Class="TestDependencyProperty827.DataTypes.DataTypeWholeNumber"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        
    xmlns:s="clr-namespace:System;assembly=mscorlib"
    xmlns:myTypes="clr-namespace:TestDependencyProperty827.DataTypes"
    >

Jadi, untuk meringkas jawaban lengkap termasuk detail tambahan dari komentar di bawah ini:

  • Kelas dasar tidak boleh menyertakan file xaml. Tentukan dalam satu file cs (non-parsial) dan tentukan untuk mewarisi langsung dari Usercontrol.
  • Pastikan subclass tersebut diturunkan dari kelas dasar di file di belakang kode cs dan di tag pertama xaml (seperti yang ditunjukkan di atas).
Martin Harris
sumber
4
ketika saya membuat perubahan itu saya mendapatkan kesalahan: "... DataTypes.BaseDataType tidak dapat menjadi root dari file XAML karena itu didefinisikan menggunakan XAML", bagaimana Anda keluar dari referensi melingkar ini?
Edward Tanguay
9
Jika Anda dapat membuat kelas dasar menjadi tipe normal yang mewarisi dari UserControl tanpa menentukan xmal (jadi bukan kelas parsial yang dibagi menjadi dua file). Masalahnya adalah Anda tidak dapat mewarisi xmal, jadi baik kelas dasar atau anak tidak perlu memiliki file xmal. Baik itu atau buat kelas Anda menjadi kontrol khusus alih-alih kontrol pengguna. Dengan cara itu tampilan didefinisikan di luar kelas parsial tetapi Anda akan kehilangan kemudahan penggunaan Kontrol Pengguna.
Martin Harris
1
Itu saja: jika Anda membuat BaseDataType sebagai kelas normal yang mewarisi UserControl, maka itu berfungsi. Luar biasa, terima kasih.
Edward Tanguay
@Martin Anda mungkin ingin memperbarui jawaban Anda untuk mencerminkan komentar Anda dan itu adalah jawaban yang sebenarnya.
Bryan Anderson
Apakah ada cara untuk membuat elemen dari "basis kontrol" berada di atas elemen di kelas yang diwarisi?
Juan M. Elosegui
2
public partial class MooringConfigurator : MooringLineConfigurator
    {
        public MooringConfigurator()
        {
            InitializeComponent();
        }
    }



<dst:MooringLineConfigurator x:Class="Wave.Dashboards.Instruments.ConfiguratorViews.DST.MooringConfigurator"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:dst="clr-namespace:Wave.Dashboards.Instruments.ConfiguratorViews.DST"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <Grid x:Name="LayoutRoot" Background="White">

    </Grid>
</dst:MooringLineConfigurator>    
Pitka
sumber
1

Saya menemukan jawabannya di artikel ini: http://www.paulstovell.com/xmlnsdefinition

Pada dasarnya apa yang dikatakan adalah bahwa Anda harus mendefinisikan namespace XML di file AssemlyInfo.cs, yang dapat digunakan di XAML. Ini berhasil untuk saya, namun saya menempatkan kelas kontrol pengguna dasar di DLL terpisah ...

lutut-cola
sumber
0

Saya mengalami masalah yang sama tetapi perlu memiliki kontrol yang diwarisi dari kelas abstrak, yang tidak didukung oleh desainer. Apa yang memecahkan masalah saya adalah membuat usercontrol mewarisi dari kelas standar (yang mewarisi UserControl) dan antarmuka. Dengan cara ini desainer bekerja.

//the xaml
<local:EcranFiche x:Class="VLEva.SIFEval.Ecrans.UC_BatimentAgricole" 
                  xmlns:local="clr-namespace:VLEva.SIFEval.Ecrans"
                  ...>
    ...
</local:EcranFiche>

// the usercontrol code behind
public partial class UC_BatimentAgricole : EcranFiche, IEcranFiche
{
    ...
}

// the interface
public interface IEcranFiche
{
   ...
}

// base class containing common implemented methods
public class EcranFiche : UserControl
{
    ... (ex: common interface implementation)
}
Sam L.
sumber
0

Ada sebagian definisi kelas yang dibuat oleh desainer, Anda dapat membukanya dengan cara mudah melalui definisi metode InitializeComponent (). Kemudian ubah saja sebagian kelas hak milik dari UserControl ke BaseDataType (atau yang Anda tentukan dalam definisi kelas).

Setelah itu Anda akan mendapat peringatan bahwa metode InitializeComponent () disembunyikan di kelas anak.

Oleh karena itu, Anda dapat menjadikan CustomControl sebagai klas dasar daripada UserControl untuk menghindari definisi parsial dalam kelas dasar (seperti yang dijelaskan dalam satu komentar).

Kakha Tengah Atau
sumber
Tidak dapat mengonversi dari Controls.Login ke Controls.BaseControl.
Himilou