MultiDataTrigger.Conditions Проверка типа привязки

Я хочу проверить, что элемент 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>
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
24
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Связывание завершается неудачно, потому что оно связывает экземпляр типа DishDTOAdvance и сравнивает его с экземпляр Type, описывающим тип DishDTOAdvance. Очевидно, что это разные типы, и условие никогда не бывает истинным. В XAML x:Type похож на typeof() или 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 для той же цели.


Бонусный раунд: триггер невозможен? Нет. Вы можете создать преобразователь, который возвращает тип.

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}"/>

Другие вопросы по теме