Come posso fornire più condizioni per l'attivazione dei dati in WPF?
Come posso fornire più condizioni per l'attivazione dei dati in WPF?
Risposte:
Usa il tipo 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 - se si desidera avere "o", annullare tutte le condizioni poiché (A e B) <=> ~ (~ A o ~ B)
ma se hai valori diversi da quelli booleani prova a usare i convertitori di tipi:
<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>
puoi usare i valori nel metodo Convert in qualsiasi modo tu voglia produrre una condizione adatta a te.
conditionConverter
fa? Come stiamo specificando "Portland" e "OR" come le nostre due or
opzioni in questo esempio?
Per elaborare la risposta di @ serine e illustrare come lavorare con una condizione multivalore non banale: avevo bisogno di mostrare un overlay "attenuato" su un elemento per la condizione booleana NOT a AND (b OR NOT c)
.
Per lo sfondo, questa è una domanda "Scelta multipla". Se l'utente sceglie una risposta errata, questa viene disabilitata (disattivata e non può essere nuovamente selezionata). Un agente automatizzato ha la capacità di concentrarsi su qualsiasi scelta particolare per dare una spiegazione (bordo evidenziato). Quando l'agente si concentra su un oggetto, non dovrebbe essere disattivato anche se è disabilitato . Tutti gli elementi che non sono a fuoco sono contrassegnati come non messi a fuoco e dovrebbero essere disattivati.
La logica per l'oscuramento è quindi:
NOT IsFocused AND (IsDefocused OR NOT Enabled)
Per implementare questa logica, ho creato un generico IMultiValueConverter
chiamato (goffamente) per abbinare la mia logica
// '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 XAML lo uso in a MultiDataTrigger
in una <Style><Style.Triggers>
risorsa
<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>
E per completezza, il mio convertitore è definito in 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>
QUESTA RISPOSTA È SOLO PER ANIMAZIONI
Se vuoi implementare la logica AND, dovresti usare MultiTrigger, ecco un esempio:
Supponiamo di voler fare alcune azioni se la proprietà Text = "" (stringa vuota) AND IsKeyboardFocused = "False", allora il codice dovrebbe essere simile al seguente:
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Text" Value="" />
<Condition Property="IsKeyboardFocused" Value="False" />
</MultiTrigger.Conditions>
<MultiTrigger.EnterActions>
<!-- Your actions here -->
</MultiTrigger.EnterActions>
</MultiTrigger>
Se vuoi implementare la logica OR, ci sono un paio di modi e dipende da cosa cerchi di fare:
La prima opzione è utilizzare più trigger.
Quindi, supponiamo che tu voglia fare qualcosa se Text = "" OR IsKeyboardFocused = "False", il
tuo codice dovrebbe assomigliare a questo:
<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>
Ma il problema in questo è che cosa farò se voglio fare qualcosa se Text ISN'T null O IsKeyboard = "True"? Ciò può essere ottenuto con il secondo approccio:
ricorda la regola di De Morgan, che dice! (! X &&! Y) = x || y.
Quindi lo useremo per risolvere il problema precedente, scrivendo un multi trigger che viene attivato quando Text = "" e IsKeyboard = "True", e faremo le nostre azioni in EXIT ACTIONS , in questo modo:
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Text" Value="" />
<Condition Property="IsKeyboardFocused" Value="False" />
</MultiTrigger.Conditions>
<MultiTrigger.ExitActions>
<!-- Do something here -->
</MultiTrigger.ExitActions>
</MultiTrigger>