Как вызвать DataTemplateSelector при изменении свойства? - PullRequest
30 голосов
/ 03 января 2012

У меня 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: (

Ответы [ 3 ]

35 голосов
/ 04 января 2012

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

FrameworkElement может иметь только EventTriggers, поэтому вы получаете сообщение об ошибке Члены коллекции триггеров должны иметь тип 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>
6 голосов
/ 03 января 2012

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

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

2 голосов
/ 04 января 2012

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

...