MultiDataTrigger.Conditions 检查绑定类型

MultiDataTrigger.Conditions Check binding type

我想检查 ListBox 元素是否具有指定视觉样式的特定类型,但常量检查失败。也许我做错了?

此行有问题:

Condition Binding="{Binding}" Value="{x:Type econemodels:DishDTOAdvance}"
<ListBox.ItemTemplate>
    <DataTemplate>
        <ContentControl Content="{Binding}">    
            <ContentControl.Style>
                <Style TargetType="ContentControl">
                    <Style.Triggers>
                        <MultiDataTrigger>
                            <MultiDataTrigger.Conditions>
                    
                                <Condition Binding="{Binding}"
                                           Value="{x:Type econemodels:DishDTOAdvance}" />
                    
                            </MultiDataTrigger.Conditions>
                            <Setter Property="ContentTemplate"
                                    Value="{StaticResource DishNoImage}" />
                        </MultiDataTrigger>
                    
                    </Style.Triggers>
                </Style>
            </ContentControl.Style>
        </ContentControl>
    </DataTemplate>
</ListBox.ItemTemplate>

绑定失败,因为它绑定了 DishDTOAdvance 类型的 实例 并在代码中将其与 Type that describes the DishDTOAdvance type. Obviously they are different types and the condition is never true. In XAML x:Type is like typeof() or GetType() 实例进行比较.

The x:Type markup extension has a similar function to the typeof() operator in C# or the GetType operator in Microsoft Visual Basic. The x:Type markup extension supplies a from-string conversion behavior for properties that take the type Type.

自定义 DataTemplateSelector 就是这种情况,不需要绑定。

Provides a way to choose a DataTemplate based on the data object and the data-bound element.

使用数据模板选择器,您可以提供任意逻辑来为项目选择数据模板。在您的情况下,类型的 switch 语句足以选择一个模板,该模板可以通过可视化树上方资源中的 FindResource 找到。当然,如果您不想搜索所有资源,也可以通过属性分配数据模板。

public class TypeTemplateSelector : DataTemplateSelector
{
   public override DataTemplate SelectTemplate(object item, DependencyObject container)
   {
      var contentPresenter = (ContentPresenter)container;

      switch (item)
      {
         case DishDTOAdvance _:
            return (DataTemplate)contentPresenter.FindResource("DishNoImage");
         // ...other type cases.
         default:
            return base.SelectTemplate(item, container);
      }
   }
}

创建数据模板选择器实例并将其添加到您的 ListBox。完全删除 ItemTemplate,它现在由选择器自动分配。

<ListBox ...>
   <ListBox.ItemTemplateSelector>
      <local:TypeTemplateSelector/>
   </ListBox.ItemTemplateSelector>
   <!-- ...other markup. -->
</ListBox>

ContentControl 是多余的。但是,如果您在项目模板中需要它,它的工作原理是一样的。 ContentControl 公开一个 ContentTemplateSelector 属性 用于相同的目的。


奖金回合:触发不可能吗?不。您可以创建一个 returns 类型的转换器。

public class TypeConverter : IValueConverter
{
   public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
   {
      return value?.GetType();
   }

   public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
   {
      throw new InvalidOperationException();
   }
}

在范围内的资源字典中创建转换器实例。

<Window.Resources>
   <local:TypeConverter x:Key="TypeConverter"/>
</Window.Resources>

在条件绑定中使用转换器。现在比较类型。

<Condition Binding="{Binding Converter={StaticResource TypeConverter}}"
           Value="{x:Type econemodels:DishDTOAdvance}"/>