Как я могу предоставить несколько условий для запуска данных в WPF?

173

Как я могу предоставить несколько условий для запуска данных в WPF?

Сумеру Суреш
источник

Ответы:

280

Использовать тип MultiDataTrigger

<Style TargetType="ListBoxItem">
    <Style.Triggers>
      <DataTrigger Binding="{Binding Path=State}" Value="WA">
        <Setter Property="Foreground" Value="Red" />
      </DataTrigger>    
      <MultiDataTrigger>
        <MultiDataTrigger.Conditions>
          <Condition Binding="{Binding Path=Name}" Value="Portland" />
          <Condition Binding="{Binding Path=State}" Value="OR" />
        </MultiDataTrigger.Conditions>
        <Setter Property="Background" Value="Cyan" />
      </MultiDataTrigger>
    </Style.Triggers>
  </Style>
Gishu
источник
28
Есть ли способ сделать оператор «ИЛИ» в multiTrigger. Например, название = "Портленд" ИЛИ штат = "ИЛИ"
Джейсон
12
@jasonk - Не уверен, что вы можете сделать это с MultiTrigger. Вы можете определить два триггера для этого ..
Гишу
2
Если это простой оператор условия OR, вы можете изменить логику, чтобы она превратилась в AND. | условие1 | условие2 | результат | | правда | правда | правда | | верно | ложно | правда | | ложь | правда | правда | | ложь | ложь | ложь | вместо проверки того, что / OR имеют значение true, проверьте, когда оба параметра AND имеют значение false, и установите для параметра по умолчанию значение true.
WeSam Абдалла
3
@WeSamAbdallah Вы не можете проверить наличие ложных условий.
Джим Балтер
4
Вы можете проверить, что условие ложно, с помощью простого конвертера.
Пол
50

@jasonk - если вы хотите иметь "или", то отмените все условия, так как (A и B) <=> ~ (~ A или ~ B)

но если у вас есть значения, отличные от логических, попробуйте использовать преобразователи типов:

<MultiDataTrigger.Conditions>
    <Condition Value="True">
        <Condition.Binding>
            <MultiBinding Converter="{StaticResource conditionConverter}">
                <Binding Path="Name" />
                <Binding Path="State" />
            </MultiBinding>
        </Condition.Binding>
        <Setter Property="Background" Value="Cyan" />
    </Condition>
</MultiDataTrigger.Conditions>

Вы можете использовать значения в методе Convert любым удобным для вас способом для создания условия, которое вам подходит.

серин
источник
3
Ах, умный ход, чтобы отрицать все и перевернуть его в состояние ИЛИ :)
myermian
8
Не могли бы вы немного расширить этот ответ? Я не уверен, как его использовать. Что делает conditionConverter? Как мы указываем «Портленд» и «ИЛИ» в качестве двух наших orвариантов в этом примере?
DLeh
4
@ cod3monk3y, ваша ссылка не работает.
Spidermain50
22

Чтобы уточнить ответ @ serine и проиллюстрировать работу с нетривиальным многозначным условием: мне нужно было показать наложение «затемнения» на элемент для логического условия NOT a AND (b OR NOT c).

Для справки, это вопрос с множественным выбором. Если пользователь выбирает неправильный ответ, он отключается (затемняется и не может быть выбран снова). Автоматизированный агент имеет возможность сосредоточиться на любом конкретном выборе, чтобы дать объяснение (граница выделена). Когда агент фокусируется на элементе, он не должен быть затемнен, даже если он отключен . Все предметы, которые не в фокусе, помечены как не сфокусированные и должны быть затемнены.

Логика для затемнения такова:

NOT IsFocused AND (IsDefocused OR NOT Enabled)

Чтобы реализовать эту логику, я сделал обобщение с IMultiValueConverterименем (неловко), чтобы соответствовать моей логике

// 'P' represents a parenthesis
//     !  a &&  ( b ||  !  c )
class NOT_a_AND_P_b_OR_NOT_c_P : IMultiValueConverter
{
    // redacted [...] for brevity
    public object Convert(object[] values, ...)
    {
        bool a = System.Convert.ToBoolean(values[0]);
        bool b = System.Convert.ToBoolean(values[1]);
        bool c = System.Convert.ToBoolean(values[2]);

        return !a && (b || !c);
    }
    ...
}

В XAML я использую это MultiDataTriggerв <Style><Style.Triggers>ресурс

<MultiDataTrigger>
    <MultiDataTrigger.Conditions>
        <!-- when the equation is TRUE ... -->
        <Condition Value="True">
            <Condition.Binding>
                <MultiBinding Converter="{StaticResource NOT_a_AND_P_b_OR_NOT_c_P}">
                    <!-- NOT IsFocus AND ( IsDefocused OR NOT Enabled ) -->
                    <Binding Path="IsFocus"/>
                    <Binding Path="IsDefocused" />
                    <Binding Path="Enabled" />
                </MultiBinding>
            </Condition.Binding>
        </Condition>
    </MultiDataTrigger.Conditions>
    <MultiDataTrigger.Setters>
        <!-- ... show the 'dim-out' overlay -->
        <Setter Property="Visibility" Value="Visible" />
    </MultiDataTrigger.Setters>
</MultiDataTrigger>

И ради полноты, мой конвертер определен в ResourceDictionary

<ResourceDictionary xmlns:conv="clr-namespace:My.Converters" ...>
    <conv:NOT_a_AND_P_b_OR_NOT_c_P x:Key="NOT_a_AND_P_b_OR_NOT_c_P" />
</ResourceDictionary>
cod3monk3y
источник
11
Я не думаю, что это цель конвертеров, которые будут использоваться таким образом. Они действительно предназначены для преобразования значений для отображения. Когда это усложняется, просто создайте вычисляемое свойство в модели представления, которое даст вам то, что вам нужно.
Мартин Каподики
13
Это название, хотя
Келли Элтон
13
Пожалуйста, уделите минутку молчания, чтобы вспомнить, когда программирование было ремеслом, а код был элегантным.
Нечеткая логика
0

ЭТОТ ОТВЕТ ТОЛЬКО ДЛЯ АНИМАЦИЙ.


Если вы хотите реализовать логику И, вы должны использовать MultiTrigger, вот пример:

Предположим, мы хотим выполнить некоторые действия, если свойство Text = "" (пустая строка) И IsKeyboardFocused = "False", тогда Ваш код должен выглядеть следующим образом:

<MultiTrigger>
    <MultiTrigger.Conditions>
        <Condition Property="Text" Value="" />
        <Condition Property="IsKeyboardFocused" Value="False" />
    </MultiTrigger.Conditions>
        <MultiTrigger.EnterActions>
            <!-- Your actions here -->
        </MultiTrigger.EnterActions>
</MultiTrigger>

Если вы хотите реализовать логику ИЛИ, есть несколько способов, и это зависит от того, что вы пытаетесь сделать:

Первый вариант - использовать несколько триггеров.
Итак, предположим, что вы хотите что-то сделать, если либо Text = "" OR IsKeyboardFocused = "False",
то ваш код должен выглядеть примерно так:

<Trigger Property="IsEnabled" Value="false">
    <Setter Property="Opacity" TargetName="border" Value="0.56"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
    <Setter Property="BorderBrush" TargetName="border" 
            Value="{StaticResource TextBox.MouseOver.Border}"/>
</Trigger>


Но проблема в том, что будет делать , если я хочу сделать что - то , если любой текст не является нулевым или IsKeyboard = «True»? Это может быть достигнуто вторым подходом:
вспомните правило де Моргана, которое гласит! (! X &&! Y) = x || у.
Таким образом, мы будем использовать его для решения предыдущей проблемы, написав мульти-триггер, который срабатывает, когда Text = "" и IsKeyboard = "True", и мы выполним наши действия в EXIT ACTIONS , например:

<MultiTrigger>
    <MultiTrigger.Conditions>
        <Condition Property="Text" Value="" />
        <Condition Property="IsKeyboardFocused" Value="False" />
    </MultiTrigger.Conditions>
    <MultiTrigger.ExitActions>
        <!-- Do something here -->
    </MultiTrigger.ExitActions>
</MultiTrigger>
Elyasaf755
источник