Wie kann ich mehrere Bedingungen für den Datenauslöser in WPF bereitstellen?
Wie kann ich mehrere Bedingungen für den Datenauslöser in WPF bereitstellen?
Antworten:
Verwenden Sie den Typ 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 - Wenn Sie "oder" haben möchten, negieren Sie alle Bedingungen seit (A und B) <=> ~ (~ A oder ~ B)
Wenn Sie jedoch andere Werte als Boolesche Werte haben, verwenden Sie Typkonverter:
<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>
Sie können die Werte in der Convert-Methode beliebig verwenden, um eine Bedingung zu erstellen, die zu Ihnen passt.
conditionConverter
? Wie geben wir or
in diesem Beispiel "Portland" und "OR" als unsere beiden Optionen an?
Um die Antwort von @ serine zu erläutern und die Arbeit mit einer nicht trivialen mehrwertigen Bedingung zu veranschaulichen: Ich musste ein "Dim-Out" -Overlay für ein Element für die boolesche Bedingung anzeigen NOT a AND (b OR NOT c)
.
Als Hintergrund ist dies eine "Multiple Choice" -Frage. Wenn der Benutzer eine falsche Antwort auswählt, wird diese deaktiviert (abgeblendet und kann nicht erneut ausgewählt werden). Ein automatisierter Agent kann sich auf eine bestimmte Auswahl konzentrieren, um eine Erklärung abzugeben (Rand hervorgehoben). Wenn sich der Agent auf ein Element konzentriert, sollte es auch dann nicht abgeblendet werden , wenn es deaktiviert ist . Alle Elemente , die nicht in fokussierter sind markiert defokussierte und sollte abgeblendet werden.
Die Logik zum Dimmen lautet also:
NOT IsFocused AND (IsDefocused OR NOT Enabled)
Um diese Logik zu implementieren, habe ich einen generischen IMultiValueConverter
Namen (umständlich) erstellt, der meiner Logik entspricht
// '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);
}
...
}
In der XAML verwende ich dies in einer MultiDataTrigger
in einer <Style><Style.Triggers>
Ressource
<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>
Der Vollständigkeit halber ist mein Konverter in a definiert 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>
DIESE ANTWORT IST NUR FÜR ANIMATIONEN
Wenn Sie die AND-Logik implementieren möchten, sollten Sie MultiTrigger verwenden. Hier ein Beispiel:
Angenommen, wir möchten einige Aktionen ausführen, wenn die Eigenschaft Text = "" (leere Zeichenfolge) AND IsKeyboardFocused = "False" ist Ihr Code sollte wie folgt aussehen:
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Text" Value="" />
<Condition Property="IsKeyboardFocused" Value="False" />
</MultiTrigger.Conditions>
<MultiTrigger.EnterActions>
<!-- Your actions here -->
</MultiTrigger.EnterActions>
</MultiTrigger>
Wenn Sie die ODER-Logik implementieren möchten, gibt es mehrere Möglichkeiten, und dies hängt davon ab, was Sie versuchen:
Die erste Option besteht darin, mehrere Trigger zu verwenden.
Angenommen, Sie möchten etwas tun, wenn entweder Text = "" ODER IsKeyboardFocused = "False",
dann sollte Ihr Code ungefähr so aussehen:
<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>
Aber das Problem dabei ist , was ich tun , wenn ich etwas tun möchte , wenn entweder Text nicht null OR IsKeyboard = „True“? Dies kann durch den zweiten Ansatz erreicht werden:
Erinnern Sie sich an die Regel von De Morgan, die besagt! (! X &&! Y) = x || y.
Wir werden es also verwenden, um das vorherige Problem zu lösen, indem wir einen Multi-Trigger schreiben, der ausgelöst wird, wenn Text = "" und IsKeyboard = "True", und wir werden unsere Aktionen in EXIT ACTIONS wie folgt ausführen :
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Text" Value="" />
<Condition Property="IsKeyboardFocused" Value="False" />
</MultiTrigger.Conditions>
<MultiTrigger.ExitActions>
<!-- Do something here -->
</MultiTrigger.ExitActions>
</MultiTrigger>