Is there a way to use data template inheritance in WPF?

Is it possible to have composition or inheritance of a DataTemplate (similar to "BasedOn" in styles)? There are two cases when I need it.

  • For legacy classes: I have a base class with several inherited classes. I do not want to duplicate the base class template in each of the derived DataTemplate class.

  • Different views: for the same class, I want to define a datatemplate, and then add to this template if necessary. Ex. the base template will display the data in the object, and then I need different templates that can perform different actions on the object while displaying the data (inheriting the base template).

+43
wpf xaml datatemplate
Dec 14 '10 at 20:00
source share
2 answers

The only thing I found for this is the following:

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

This basically creates a β€œgeneric” template that can be referenced using a key (in this case, BaseClass). Then we define the real DataTemplate for the base class and any derived classes. A derived class template would then add its own β€œmaterial”.

There was some discussion about this on msdn a while ago, but no one came up with the best solution I saw.

+39
Dec 14 '10 at 20:15
source share

@Fragilerus and @Liz, in fact, I think I came up with something better. Here is another approach that not only avoids the additional ContentPresenter binding, but also eliminates the need to use a template in a template, since shared content is direct content that is installed at compile time. The only thing that happens at runtime is the bindings that you set inside the direct content. Thus, it greatly speeds up the user interface compared to another 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. Be sure to use the x:Shared attribute in your shared content, otherwise this will not work.

WPF'y Way

From the above, this is really not the most convenient way for WPF to do what you need. This can be achieved using the DataTemplateSelector class, which does just that ... choosing a data template based on any criteria you set.

For example, you can easily install one of them that searches for your known data types and returns the same DataTemplate for both of them, but for all other types it returns to the system to resolve the DataTemplate. This is what we are actually doing here.

Hope this helps! :)

+21
May 7 '11 at 8:46 am
source share



All Articles