Як я можу забезпечити декілька умов для запуску даних у 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>

28
Чи є спосіб зробити операцію "АБО" у мультитригері. наприклад, назва = "портланд" АБО стан = "АБО"
jasonk

12
@jasonk - Не впевнений, чи можна це зробити за допомогою MultiTrigger. Ви можете визначити два тригери для цього ..
Gishu

2
Якщо це звичайний оператор АБО умова, ви можете змінити логіку, щоб вона перетворилася на І. | умова1 | стан2 | результат | | справжній | правдивий | правда | | правдиві | хибні | правда | | помилкові | правдиві | правда | | помилкові | помилкові | помилкові | замість того, щоб перевірити, чи / ІЛИ є істинними, перевірте, коли обидва / ІЛИ є помилковими, і встановіть значення за замовчуванням на істинне.
WeSam Abdallah

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>

ви можете використовувати значення методу «Перетворити» будь-яким способом, щоб створити умову, яка вам підходить.


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>

А для повноти мій перетворювач визначений в a 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>

11
Я не думаю, що це такий спосіб використання перетворювачів. Вони справді призначені для перетворення значень для відображення. Коли це ускладнюється, просто створіть обчислену властивість на моделі перегляду, яка дає вам те, що вам потрібно.
Мартін Каподічі

13
Це називання, хоча
Келлі Елтон

13
Будь ласка, заспокоїте хвилину мовчання, щоб згадати, коли програмування було ремеслом, а код - елегантним.
Нечітка логіка

0

ЦІЙ ВІДПОВІДЬ


ТІЛЬКО АНІМАЦІЙ Якщо ви хочете реалізувати логіку AND, вам слід скористатись MultiTrigger, ось ось приклад:

Припустимо, ми хочемо виконати деякі дії, якщо властивість Text = "" (порожня рядок) AND 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 = "" АБО IsKeyboardFocused = "Невірно",
ваш код повинен виглядати приблизно так:

<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 = "Істинно"? Цього можна досягти другим підходом:
пригадайте правило Де Моргана, яке говорить! (! X &&! Y) = x || у.
Таким чином , ми будемо використовувати його для вирішення попередньої задачі, написавши мульти тригер, він спрацьовує , коли Text = "" і IsKeyboard = «True», і ми зробимо все наші дії в ВИЇЗНИХ ЗАХОДІВ , як це:

<MultiTrigger>
    <MultiTrigger.Conditions>
        <Condition Property="Text" Value="" />
        <Condition Property="IsKeyboardFocused" Value="False" />
    </MultiTrigger.Conditions>
    <MultiTrigger.ExitActions>
        <!-- Do something here -->
    </MultiTrigger.ExitActions>
</MultiTrigger>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.