Jak mogę podać wiele warunków dla wyzwalacza danych w WPF?
Jak mogę podać wiele warunków dla wyzwalacza danych w WPF?
Odpowiedzi:
Użyj typu 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>
@jasonk - jeśli chcesz mieć „lub”, zaneguj wszystkie warunki od (A i B) <=> ~ (~ A lub ~ B)
ale jeśli masz wartości inne niż logiczne, spróbuj użyć konwerterów typów:
<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>
możesz użyć wartości w metodzie Convert w dowolny sposób, aby stworzyć warunek, który Ci odpowiada.
conditionConverter
robi? W jaki sposób określamy „Portland” i „OR” jako dwie or
opcje w tym przykładzie?
Aby rozwinąć odpowiedź @ serine i zilustrować pracę z nietrywialnym warunkiem wielowartościowym: Musiałem pokazać nakładkę „dim-out” na elemencie dla warunku boolowskiego NOT a AND (b OR NOT c)
.
W tle jest to pytanie „wielokrotnego wyboru”. Jeśli użytkownik wybierze złą odpowiedź, zostaje ona wyłączona (wygaszona i nie można jej ponownie wybrać). Automatyczny agent może skupić się na każdym konkretnym wyborze, aby udzielić wyjaśnienia (obramowanie podświetlone). Gdy agent skupia się na elemencie, nie powinien być wygaszany, nawet jeśli jest wyłączony . Wszystkie elementy, które nie są skupione, są oznaczone jako nieostre i powinny być wygaszone.
Logika ściemniania jest następująca:
NOT IsFocused AND (IsDefocused OR NOT Enabled)
Aby zaimplementować tę logikę, stworzyłem rodzaj o IMultiValueConverter
nazwie (niezręcznie), aby pasował do mojej logiki
// '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);
}
...
}
W XAML używam tego w sposób MultiDataTrigger
w <Style><Style.Triggers>
zasobie
<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>
Ze względu na kompletność mój konwerter jest zdefiniowany w pliku 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>
TA ODPOWIEDŹ DOTYCZY WYŁĄCZNIE ANIMACJI
Jeśli chcesz zaimplementować logikę AND, powinieneś użyć MultiTrigger, oto przykład:
Załóżmy, że chcemy wykonać jakieś akcje, jeśli właściwość Text = "" (pusty ciąg) AND IsKeyboardFocused = "False", a następnie Twój kod powinien wyglądać następująco:
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Text" Value="" />
<Condition Property="IsKeyboardFocused" Value="False" />
</MultiTrigger.Conditions>
<MultiTrigger.EnterActions>
<!-- Your actions here -->
</MultiTrigger.EnterActions>
</MultiTrigger>
Jeśli chcesz wdrożyć logikę OR, istnieje kilka sposobów i zależy to od tego, co próbujesz zrobić:
Pierwszą opcją jest użycie wielu wyzwalaczy.
Więc załóżmy, że chcesz coś zrobić, jeśli albo Text = "" LUB IsKeyboardFocused = "False",
wtedy Twój kod powinien wyglądać mniej więcej tak:
<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>
Ale problem polega na tym, co mam zrobić, jeśli chcę coś zrobić, jeśli albo tekst NIE JEST null, LUB IsKeyboard = "True"? Można to osiągnąć poprzez drugie podejście:
Przypomnij sobie regułę De Morgana, która mówi! (! X &&! Y) = x || y.
Więc użyjemy go do rozwiązania poprzedniego problemu, pisząc wyzwalacz wielokrotny, który jest wyzwalany, gdy Text = "" i IsKeyboard = "True", a nasze działania wykonamy w EXIT ACTIONS , na przykład:
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Text" Value="" />
<Condition Property="IsKeyboardFocused" Value="False" />
</MultiTrigger.Conditions>
<MultiTrigger.ExitActions>
<!-- Do something here -->
</MultiTrigger.ExitActions>
</MultiTrigger>