WPF - как совместить DataTrigger и Trigger?

ПРИМЕЧАНИЕ. Я задал связанный вопрос: Как объединить DataTrigger и EventTrigger?

У меня есть список, содержащий несколько пунктов. Класс элемента реализует INotifyPropertyChanged и имеет свойство IsAvailable. Я использую это свойство для обозначения недоступных опций в списке другим цветом.

Однако, если выбранный элемент недоступен, цвет переднего плана должен быть красным.

<ListBox>
  <ListBox.Resources>
    <DataTemplate DataType="{x:Type local:InstitutionViewModel}">
      <TextBlock Name="Name" Text="{Binding Name}"/>
      <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding IsAvailable}" Value="False">
          <Setter TargetName="Name" Property="Foreground" Value="#888"/>
        </DataTrigger>
      </DataTemplate.Triggers>
    </DataTemplate>
  </ListBox.Resources>
</ListBox>

Я использую указанный выше триггер данных, чтобы выделить недоступные элементы серым цветом.

Проблема, с которой я столкнулся, заключается в том, что тот факт, что элемент выбран, не имеет ничего общего с базовыми данными, к которым привязан шаблон. Что мне действительно нужно, так это какой-то мульти-триггер, который поддерживает как обычный Trigger для свойства зависимости (ListBoxItem.IsSelected), так и DataTrigger для привязанного элемента данных.

Можно ли это сделать без введения концепции выбора в мою модель представления?

Тем, кто задается вопросом, почему я не отключаю недоступные элементы, следует понимать, что это требование приложения, чтобы можно было выбирать недоступные параметры. На самом деле есть несколько списков, и выбор в одном из них влияет на то, что доступно в других. Я не могу отключить элементы, так как пользователь не сможет изменить свое мнение или изучить различные комбинации, если элементы были отключены на основании ранее сделанного выбора.


person Drew Noakes    schedule 02.03.2009    source источник


Ответы (2)


Для всех, кто сталкивается с этой проблемой, я нашел решение, которое работает для меня. Конечно, мне все еще интересно увидеть другие интересные ответы.

Вот что я сделал:

<MultiDataTrigger>
  <MultiDataTrigger.Conditions>
    <Condition Binding="{Binding
      RelativeSource={
        RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}},
        Path=IsSelected}" Value="True"/>
    <Condition Binding="{Binding IsAvailable}" Value="False"/>
  </MultiDataTrigger.Conditions>
  <Setter TargetName="Name" Property="Foreground" Value="#F00"/>
</MultiDataTrigger>

Однако нет ничего особенного в том, что это мульти-триггер. Если вы просто хотите изменить стиль выбранного элемента в шаблоне данных, вы можете использовать:

<DataTrigger Binding="{Binding 
  RelativeSource={
    RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}},
    Path=IsSelected}" Value="True">
  <Setter TargetName="Name" Property="Foreground" Value="#888"/>
</DataTrigger>
person Drew Noakes    schedule 02.03.2009
comment
Это именно то, что я собирался порекомендовать. Насколько я знаю, это лучшее решение. - person Bryan Anderson; 02.03.2009
comment
просто ударьте ту же проблему. Отличный чувак, забыл об относительной привязке источника. - person EightyOne Unite; 07.10.2009

Чтобы использовать его с DataGridRow, измените режим привязки на Self:

Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=... 
person Vadim    schedule 01.12.2010
comment
Кроме того, если вы пытаетесь использовать Path=Selector.IsSelectionActive, вместо этого используйте Path=(Selector.IsSelectionActive), потому что это присоединенное свойство. - person Andrew; 18.11.2019