属性更改时如何触发DataTemplateSelector?

时间:2012-01-03 16:28:48

标签: c# wpf 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。有什么建议吗?

Threre是类似的问题: 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 个答案:

答案 0 :(得分:35)

正如您在评论中请求了数据触发器的示例,您在这里:

FrameworkElement只能有EventTriggers,因此您会收到错误消息触发器集合成员必须是EventTrigger类型

并且不要直接使用ContentPresenter,它应该在ControlTemplate中使用。当您想拥有动态内容时,最好使用ContentControl。 见What's the difference between ContentControl and 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>

答案 1 :(得分:6)

我可能错了,但我相信DataTemplateSelector仅在ItemContainerGenerator为添加到集合中的项目创建容器时使用。由于在属性值更改时未生成新容器,因此永远不会通过选择器应用新的DataTemplate

正如评论中所建议的那样,我建议您查看VisualStateManager或数据触发器,否则当一个或多个属性更改值时,您将不得不为每个项重新创建容器。

答案 2 :(得分:2)

作为一个额外的选择 - 如果你想坚持你的模板,只需使用s绑定转换器。