Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF DataTemplate Binding depending on the type of a property

I have a collection of objects bound to a hierarchical data template, each of my objects have a property on them (lets call it Property "A") that is of a certain type. This type varies among each of the objects.

If the data template contains an image and some text, what would be the best way to change the image that is displayed in the template based on the type of property "A".

I know I could just stick this into a converter and do the binding translation manually in code, but with all the binding facilities available in WPF, I think theres probably a better way.

like image 557
gmn Avatar asked Feb 15 '11 22:02

gmn


People also ask

What is difference between a ControlTemplate and a DataTemplate in WPF?

A ControlTemplate will generally only contain TemplateBinding expressions, binding back to the properties on the control itself, while a DataTemplate will contain standard Binding expressions, binding to the properties of its DataContext (the business/domain object or view model).

Where do you put DataTemplate?

According to Microsofts App Studio the DataTemplates should live in a DataTemplates Subdirectory under the Views Directory.

How does data binding work in WPF?

Data binding is a mechanism in WPF applications that provides a simple and easy way for Windows Runtime apps to display and interact with data. In this mechanism, the management of data is entirely separated from the way data. Data binding allows the flow of data between UI elements and data object on user interface.


2 Answers

It's pretty simple to do this within your data template, if you create local data templates and use a ContentPresenter. This template presents objects of type MyObject, displaying an image whose source is determined by the type of the A property next to a TextBlock that displays the content of the Text property:

<DataTemplate DataType="{x:Type MyObject}">
   <StackPanel Orientation="Horizontal">
      <StackPanel.Resources>
         <DataTemplate DataType="{x:Type Thing1}">
            <Image Source="thing1.png"/>
         </DataTemplate>
         <DataTemplate DataType="{x:Type Thing2}">
            <Image Source="thing2.png"/>
         </DataTemplate>
      </StackPanel.Resources>
      <ContentPresenter Content="{Binding A}"/>
      <TextBlock Text="{Binding Text}"/>
   </StackPanel>
</DataTemplate>

If you want to use styles to do this instead, you're going to run into a problem, because data triggers want to look at property values, and the type of the A property is not, itself, exposed as a property.

Unless, of course, you implement one:

public Type AType { get { return A.GetType(); } }

(You'll also need to raise PropertyChanged for AType when the value of A changes.) Once you've done this, you should be able to implement a data trigger in a style, e.g.:

<Style TargetType="Image">
   <Setter Property="Source" Value="default.png"/>
   <Style.Triggers>
      <DataTrigger Binding="{Binding AType}" Value="{x:Type Thing1}">
         <Setter Property="Source" Value="thing1.png"/>
      </DataTrigger>
      <DataTrigger Binding="{Binding AType}" Value="{x:Type Thing2}">
         <Setter Property="Source" Value="thing2.png"/>
      </DataTrigger>
   </Style.Triggers>
</Style>
like image 181
Robert Rossney Avatar answered Oct 11 '22 11:10

Robert Rossney


I think You can do that with triggers.

<Image.Style>
    <Style TargetType="{x:Type Image}">
        <Setter Property="Source" Value="Path">
        <Style.Triggers>
            <DataTrigger Binding="{Binding TheProperty}" Value="TheValue">
                <Setter Property="Source" Value="NewPath"/>
            </DataTrigger>
        </Style.Triggers>
     </Style>
</Image.Style>
like image 22
Matěj Zábský Avatar answered Oct 11 '22 11:10

Matěj Zábský