Подтвердить что ты не робот

Как вызвать DataTemplateSelector при изменении свойств?

У меня есть ContentPresenter с 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;
    }

При изменении CurrentStatus вызывается OnPropertyChanged.

Мне нужно каким-то образом запустить этот DataTemplateSelector, когда свойство будет изменено и изменится ContentPresenter DataTemplate. Любые предложения?

Вот такие вопросы: 1 2, но я не хочу использовать DataTriggers из-за слишком большого количества состояний.

Пробовал играть с 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>

Но получилась ошибка: Элементы коллекции триггеров должны иметь тип EventTrigger: (

4b9b3361

Ответ 1

Как вы запросили пример с datatriggers в комментариях, вот вы:

Элемент FrameworkElement может иметь только EventTriggers, поэтому вы получаете сообщение об ошибке. Элементы коллекции Triggers сообщения должны иметь тип EventTrigger

И также не используйте ContentPresenter напрямую, он предназначен для использования внутри ControlTemplate. Лучше использовать ContentControl, если вы хотите иметь динамический контент. См. В чем разница между ContentControl и ContentPresenter?

И, наконец, вот предложение к вашей проблеме DataTrigger. Я положил его в стиле для повторного использования....

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>

Ответ 2

Я мог ошибаться, но я считаю, что DataTemplateSelector используется, когда ItemContainerGenerator создает контейнер для элемента, добавленного в коллекцию. Поскольку новый контейнер не генерируется при изменении значения свойства, новый DataTemplate никогда не будет применяться через селектор.

Как указано в комментариях, я бы рекомендовал вам посмотреть триггеры VisualStateManager или данных, иначе вам придется воссоздавать контейнер для каждого элемента, когда одно или несколько свойств изменяют значение.

Ответ 3

Как дополнительный выбор - если вы хотите придерживаться своих шаблонов, просто используйте привязку s с конвертером.