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