Search code examples
c#wpfdatatemplateselector

How to trigger DataTemplateSelector when property changes?


I have ContentPresenter with DataTemplateSelector:

    ...

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        var model = item as ItemControlViewModel;

        if (model.CurrentStatus == PrerequisitesStatus.Required)
        {
            return RequiredTemplate;
        }

        if (model.CurrentStatus == PrerequisitesStatus.Completed)
        {
            return FinishedTemplate;
        }

        ...

        return InProgressTemplate;
    }

When CurrentStatus is changed, OnPropertyChanged is called.

I need somehow to trigger this DataTemplateSelector when the property is changed and change ContentPresenter DataTemplate. Any suggestions?

Threre are similar questions: 1 2, but I don't want to use any DataTriggers, because of too much states.

Tried to play with DataTriggers

    <ContentPresenter
        Grid.Column="1"
        Height="16"
        Width="16"
        Margin="3">
        <ContentPresenter.Triggers>
            <DataTrigger Binding="{Binding Path=CurrentStatus}" Value="0">
                <Setter Property="ContentPresenter.ContentTemplate" Value="{StaticResource ResourceKey=_requiredStatusTemplate}" />
            </DataTrigger>
        </ContentPresenter.Triggers>
    </ContentPresenter>

But got an error: Triggers collection members must be of type EventTrigger :(


Solution

  • As you requested an example with datatriggers in the comments, here you are:

    A FrameworkElement can only have EventTriggers, therefore you get the error Message Triggers collection members must be of type EventTrigger

    And also don't use a ContentPresenter directly, it is meant to be used inside a ControlTemplate. Better use a ContentControl when you want to have dynamic content. See What's the difference between ContentControl and ContentPresenter?

    And finally here's a suggestion to your DataTrigger issue. I have put it inside a style for reusability ....

    XAML :

    <Window x:Class="WpfApplication88.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
      <Window.Resources>
    
        <DataTemplate x:Key="requiredTemplate">
          <TextBlock Text="requiredTemplate"></TextBlock>
          <!--your stuff here-->
        </DataTemplate>
    
        <DataTemplate x:Key="completedTemplate">
          <TextBlock Text="CompletedTemplate"></TextBlock>
          <!--your stuff here-->
        </DataTemplate>
    
        <Style x:Key="selectableContentStyle" TargetType="{x:Type ContentControl}">
          <Style.Triggers>
            <DataTrigger Binding="{Binding Path=CurrentStatus}" Value="Required">
              <Setter Property="ContentTemplate" Value="{StaticResource requiredTemplate}" />
            </DataTrigger>
            <DataTrigger Binding="{Binding Path=CurrentStatus}" Value="Completed">
              <Setter Property="ContentTemplate" Value="{StaticResource completedTemplate}" />
            </DataTrigger>
            <!--  your other Status' here -->
          </Style.Triggers>
        </Style>
    
      </Window.Resources>
    
      <Grid>
        <ContentControl Width="100" Height="100" Style="{StaticResource selectableContentStyle}"/>
      </Grid>
    
    </Window>