【问题标题】:WPF Trigger based on Object Type基于对象类型的 WPF 触发器
【发布时间】:2010-12-11 18:15:47
【问题描述】:

有没有办法比较触发器的对象类型?

<DataTrigger Binding="{Binding SelectedItem}" Value="SelectedItem's Type">
</DataTrigger>

背景:我有一个工具栏,我想根据当前为所选项目对象设置的子类隐藏按钮。

谢谢

【问题讨论】:

    标签: wpf xaml types binding datatrigger


    【解决方案1】:

    为什么不直接使用一个转换器,它接受一个对象并返回一个对象类型的字符串?

    Binding="{Binding SelectedItem, Converter={StaticResource ObjectToTypeString}}"

    并将转换器定义为:

    public class ObjectToTypeStringConverter : IValueConverter
    {
        public object Convert(
         object value, Type targetType,
         object parameter, System.Globalization.CultureInfo culture)
        {
            return value.GetType().Name;            
        }
    
        public object ConvertBack(
         object value, Type targetType,
         object parameter, System.Globalization.CultureInfo culture)
        {
            // I don't think you'll need this
            throw new Exception("Can't convert back");
        }
    }
    

    您需要在 xaml 中的某处声明静态资源:

    <Window.Resources>
        <convs:ObjectToTypeStringConverter x:Key="ObjectToTypeString" />
    </Window.Resources>
    

    这里的“convs”是转换器所在的命名空间。

    希望这会有所帮助。

    【讨论】:

    • +1 表示总体思路,但是转换器应返回 Type 对象而不是其名称...
    • 这行得通吗?运行时不会将 String 类型的东西与 Type 类型的东西进行比较吗?我知道它处理转换/比较大多数值类型,但不熟悉它如何处理其他类型比较。
    • 是的,它会起作用,您只需在 DataTrigger 的值中使用 {x:Type} 标记扩展。
    【解决方案2】:

    使用 AndyG 建议的转换器是一个不错的选择。或者,您也可以为每种目标类型使用不同的DataTemplate。 WPF 会自动选择匹配对象类型的DataTemplate

    【讨论】:

    • 但它也会影响该数据类型的每个子元素
    【解决方案3】:

    这是基于@AndyG 的回答,但更安全一些,因为它是强类型的。

    实现一个名为 DataTypeConverter 的 IValueConverter,它接受一个对象并返回其类型(作为 System.Type):

    public class DataTypeConverter:IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, 
          CultureInfo culture)
        {
            return value?.GetType() ?? Binding.DoNothing;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter,
          CultureInfo culture)
        {
           throw new NotImplementedException();
        }
    }
    

    更改您的 DataTrigger 以使用转换器,并将值设置为类型:

    <DataTrigger Binding="{Binding SelectedItem,  
          Converter={StaticResource DataTypeConverter}}" 
          Value="{x:Type local:MyType}">
    ...
    </DataTrigger>
    

    在资源中声明DataTypeConverter:

    <UserControl.Resources>
        <v:DataTypeConverter x:Key="DataTypeConverter"></v:DataTypeConverter>
    </UserControl.Resources>
    

    【讨论】:

    • 这对我不起作用。如果我尝试在 DataTrigger.Value 中使用标记扩展,则会收到 XamlParseException,因此我只是使用了字符串比较方法。见这里:social.msdn.microsoft.com/Forums/en-US/wpf/thread/…
    • 在尝试 GetType() 之前最好检查值是否为空。返回值!= null ? value.GetType() : null;
    • Binding="{Binding SelectedItem}" Converter={StaticResource DataTypeConverter}}" 应该是Binding="{Binding SelectedItem, Converter={StaticResource DataTypeConverter}}"
    【解决方案4】:

    不是触发器,但这对我有用。 (触发器方法没有,因为它无法为字符串创建复选框。这几乎是Thomas Levesque's suggestion

    使用:

    xmlns:mscorlib="clr-namespace:System;assembly=mscorlib"
    

    取决于类型的 CheckBox 或 TextBox:

    <ContentPresenter Content="{TemplateBinding SelectedItem}">
          <ContentPresenter.Resources>
                   <DataTemplate DataType="{x:Type mscorlib:Boolean}">
                        <CheckBox Height="25" Width="25" HorizontalAlignment="Left" IsChecked="{Binding Path=.}"/>
                   </DataTemplate>
                      <DataTemplate DataType="{x:Type mscorlib:String}">
                        <TextBox Height="25" Width="200" HorizontalAlignment="Left" Text="{Binding Path=.}"/>
                    </DataTemplate>
           </ContentPresenter.Resources>
    </ContentPresenter>
    

    注意:对于 Greg Sansom 的解决方案,您要么将类型返回为 String,要么使用上面的 mscorlib

    【讨论】:

      【解决方案5】:

      如果您可以通过添加属性来修改分配给“SelectedItem”的(基本)类型:

      public Type Type => this.GetType();
      

      然后你可以像这样在 xaml 中使用 DataTrigger:

      <DataTrigger Binding="{Binding SelectedItem.Type}" Value="{x:Type local:MyClass}">
      </DataTrigger>
      

      与 AndyG 的好答案相比的优势在于,您在 XAML 中没有您的类型的魔术字符串,但所有内容都可以安全编译。 缺点:您需要修改模型 - 这可能并不总是可行的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-07-19
        • 2016-12-28
        • 1970-01-01
        • 2018-04-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多