it-roy-ru.com

Триггер WPF на основе типа объекта

Есть ли способ сделать сравнение по типу объекта для триггера?

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

Фон: у меня есть панель инструментов, и я хочу скрыть кнопки в зависимости от того, какой подкласс в настоящее время установлен для выбранного объекта элемента.

Спасибо

35
Exist

Почему бы просто не использовать конвертер, который принимает объект и возвращает строку типа объекта?

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' в этом случае - это пространство имен того, где находится конвертер.

Надеюсь это поможет.

31
AndyG

Это основано на ответе @ AndyG, но немного безопаснее, потому что оно строго типизировано.

Реализуйте IValueConverter с именем DataTypeConverter, который принимает объект и возвращает его тип (как System.Type):

public class DataTypeConverter: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 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>
44
Greg Sansom

Не триггер, но это сработало для меня. (Триггерный подход не сработал, поскольку не может создать флажок для строки. Это в значительной степени предложение Томаса Левеска )

с помощью:

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>

Примечание: для решения Грега Сансома вы должны либо вернуть тип как String, либо использовать mscorlib, как указано выше.

4
mYnDstrEAm

Использование конвертера, предложенного AndyG, является хорошим вариантом. В качестве альтернативы, вы также можете использовать разные DataTemplate для каждого целевого типа. WPF автоматически выберет DataTemplate, который соответствует типу объекта

4
Thomas Levesque

Если вы в состоянии изменить (базовый) тип, назначенный для SelectedItem, добавив свойство:

public Type Type => this.GetType();

Тогда вы можете использовать DataTrigger в xaml следующим образом:

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

Преимущество по сравнению с хорошим ответом AndyG заключается в том, что у вас нет магической строки вашего типа в XAML, но все безопасно для компиляции. Недостаток: вам нужно изменить модель, что не всегда возможно.

0
sam