Existe-t-il un moyen d'utiliser l'héritage des modèles de données dans WPF?

Est-il possible d'avoir DataTemplate composition ou héritage (semblable à "BasedOn" dans les Styles)? Il y a 2 cas où j'en ai besoin.

  1. pour les classes héritées: j'ai une classe de base avec plusieurs classes héritées. Je ne veux pas dupliquer le modèle de classe de base dans chacune des classes dérivées DataTemplate.

  2. vues différentes: pour la même classe, je veux définir un datatemplate, puis l'ajouter à ce modèle comme approprié. Ex. le base template affichera les données dans l'objet et puis je veux différents modèles qui peuvent effectuer différentes actions sur l'objet, tout en affichant les données (hériter le modèle de base).

46
demandé sur Anatoliy Nikolaev 2010-12-14 23:00:32

2 réponses

La seule chose que j'ai trouvé à faire pour ce genre de chose, c'est ceci:

<DataTemplate x:Key="BaseClass">
  <!-- base class template here -->
</DataTemplate>
<DataTemplate DataType="{x:Type app:BaseClass}">
  <ContentPresenter Content="{Binding}" 
                    ContentTemplate="{StaticResource BaseClass}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type app:DerivedClass}">
  <StackPanel>
    <ContentPresenter Content="{Binding}" 
                      ContentTemplate="{StaticResource BaseClass}"/>
    <!-- derived class extra template here -->
  </StackPanel>
</DataTemplate>

fondamentalement cela crée un modèle" commun " qui peut être référencé en utilisant une clé (classe de base dans ce cas). Ensuite nous définissons le véritable DataTemplate pour la classe de base, et toutes les classes dérivées. Le modèle de classe dérivé ajouterait alors son propre "truc".

Il y a des discussions à ce sujet sur msdn il y a quelque temps, mais personne n'a trouvé de meilleure solution que moi scie.

43
répondu Liz 2016-05-23 17:46:58

@Fragilerus et @Liz, en fait je pense que j'ai trouvé quelque chose de mieux. Voici une autre approche qui non seulement évite le Contenupresenter contraignant supplémentaire, mais supprime également la nécessité d'avoir à appliquer un modèle dans un modèle puisque le contenu partagé est du contenu direct qui est défini au moment de la compilation. La seule chose qui se produit à l'exécution serait les fixations que vous mettez à l'intérieur du contenu direct. Par conséquent, l'assurance-chômage s'en trouve grandement accélérée par rapport à l'autre. solution.

<!-- Content for the template (note: not a template itself) -->
<Border x:Shared="False" 
        x:Key="Foo" 
        BorderBrush="Red" 
        BorderThickness="1" 
        CornerRadius="4">
    <TextBlock Text="{Binding SomeProp}" />
</Border>

<DataTemplate x:Key="TemplateA">
    <!-- Static resource - No binding needed -->
    <ContentPresenter Content="{StaticResource Foo}" /> 
</DataTemplate>

<DataTemplate x:Key="TemplateB">
    <!-- Static resource - No binding needed -->
    <ContentPresenter Content="{StaticResource Foo}" />
</DataTemplate>

Important: assurez-vous d'utiliser le x:Shared l'attribut sur votre contenu partagé ou cela ne fonctionnera pas.

WPF y

ceci dit, ce n'est vraiment pas la façon la plus conviviale de faire ce que vous cherchez. Cela peut être réalisé en utilisant la classe DataTemplateSelector qui fait exactement cela... sélectionnez un modèle de données basé sur des critères que vous définissez.

Par exemple, vous pouvez facilement en créer un qui ressemble pour votre les types de données et renvoie le même Dataatemplate pour les deux types, mais pour tous les autres types, il revient au système de résoudre le Dataatemplate. C'est ce que nous faisons ici.

Espérons que cette aide! :)

22
répondu MarqueIV 2017-02-21 05:08:20