Come può un UserControl WPF ereditare un UserControl WPF?


92

Il seguente UserControl WPF chiamato DataTypeWholeNumber che funziona.

Ora voglio creare un UserControl chiamato DataTypeDateTime e DataTypeEmail , ecc.

Molte delle proprietà di dipendenza saranno condivise da tutti questi controlli e quindi desidero inserire i loro metodi comuni in un BaseDataType e fare in modo che ciascuno di questi controlli utente erediti da questo tipo di base.

Tuttavia, quando lo faccio, ottengo l' errore: la dichiarazione parziale potrebbe non avere classi di base diverse .

Quindi come posso implementare l'ereditarietà con UserControls in modo che la funzionalità condivisa sia tutta nella classe base?

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());



    }
}

per la soluzione alternativa WPF con ereditarietà visiva vedere: svetoslavsavov.blogspot.gr/2009/09/… o per definire esplicitamente la GUI nell'antenato vedere support.microsoft.com/kb/957231
George Birbilis

Risposte:


130

Assicurati di aver modificato il primo tag in xaml per ereditare anche dal tuo nuovo tipo di base

Così

<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"
    >

diventa

<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"
    >

Quindi, per riassumere la risposta completa inclusi i dettagli extra dai commenti di seguito:

  • La classe base non dovrebbe includere un file xaml. Definiscilo in un singolo file cs (non parziale) e definiscilo in modo che erediti direttamente da Usercontrol.
  • Assicurati che la sottoclasse erediti dalla classe base sia nel file code-behind cs che nel primo tag di xaml (come mostrato sopra).

4
quando apporto questa modifica ottengo l'errore: "... DataTypes.BaseDataType non può essere la radice di un file XAML perché è stato definito utilizzando XAML", come si esce da questo riferimento circolare?
Edward Tanguay,

9
Se puoi semplicemente rendere la classe base un tipo normale che eredita da UserControl senza definire alcun xmal (quindi non una divisione parziale della classe su due file). Il problema è che non puoi ereditare xmal, quindi né la classe base né quella figlia non devono avere un file xmal. O quello o crea controlli personalizzati delle tue classi invece di controlli utente. In questo modo l'aspetto è definito al di fuori della classe parziale ma perderai la facilità d'uso di un controllo utente.
Martin Harris,

1
Ecco fatto: se rendi BaseDataType una classe normale che eredita UserControl, allora funziona. Eccellente grazie.
Edward Tanguay,

@Martin potresti voler aggiornare la tua risposta per riflettere il tuo commento ed è la vera risposta.
Bryan Anderson

C'è un modo per fare in modo che gli elementi della "base di controllo" siano in cima a quelli della classe che eredita?
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>    

1

Ho trovato la risposta in questo articolo: http://www.paulstovell.com/xmlnsdefinition

Fondamentalmente ciò che viene detto è che dovresti definire uno spazio dei nomi XML nel file AssemlyInfo.cs, che può essere utilizzato in XAML. Ha funzionato per me, tuttavia ho inserito la classe di controllo utente di base in una DLL separata ...


0

Mi sono imbattuto nello stesso problema ma avevo bisogno che il controllo ereditasse da una classe astratta, che non è supportata dal designer. Ciò che ha risolto il mio problema è stato far ereditare da usercontrol sia una classe standard (che eredita UserControl) che un'interfaccia. In questo modo il designer sta lavorando.

//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)
}

0

Esiste una definizione di classe parziale creata dal designer, è possibile aprirla in modo semplice tramite la definizione del metodo InitializeComponent (). Quindi cambia semplicemente l'ereditarietà della classe parziale da UserControl a BaseDataType (o qualsiasi altra specificata nella definizione della classe).

Dopodiché avrai un avviso che il metodo InitializeComponent () è nascosto nella classe figlia.

Pertanto è possibile creare un CustomControl come classe di base invece di UserControl per evitare una definizione parziale nella classe base (come descritto in un commento).


Impossibile convertire da Controls.Login a Controls.BaseControl.
Himilou
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.