Come posso fornire più condizioni per l'attivazione dei dati in WPF?


Risposte:


280

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>

28
Esiste un modo per eseguire un'istruzione "OR" nel multiTrigger. ad esempio il nome = "portland" O lo stato = "OR"
jasonk,

12
@jasonk - Non sono sicuro di poterlo fare con un MultiTrigger. Puoi definire due trigger per questo ...
Gishu,

2
Se si tratta di una semplice istruzione OR, è possibile invertire la logica in modo che si trasformi in AND. | condition1 | condition2 | risultato | | true | true | vero | | true | false | vero | | false | true | vero | | false | false | falso | invece di verificare che uno dei due / OR sia vero, controlla quando entrambi / AND sono falsi e imposta il valore predefinito su true.
WeSam Abdallah,

3
@WeSamAbdallah Non è possibile verificare la presenza di condizioni false.
Jim Balter,

4
È possibile verificare che una condizione sia falsa da un semplice convertitore.
Paul,

50

@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.


3
Ah, mossa intelligente per negare tutto e capovolgerlo su una condizione OR :)
myermian

8
Potresti per favore ampliare un po 'questa risposta? Non sono sicuro di come usarlo. Che cosa conditionConverterfa? Come stiamo specificando "Portland" e "OR" come le nostre due oropzioni in questo esempio?
DLeh,

4
@ cod3monk3y, il tuo collegamento è interrotto.
Spidermain50,

22

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 IMultiValueConverterchiamato (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 MultiDataTriggerin 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>

11
Non penso che questo sia l'intento dei convertitori di essere utilizzati in questo modo. Sono davvero pensati per convertire valori per la visualizzazione. Quando diventa complicato, basta creare una proprietà calcolata sul modello di visualizzazione che ti dia ciò di cui hai bisogno.
Martin Capodici,

13
Quella denominazione però
Kelly Elton il

13
Per favore, prenditi un momento di silenzio da ricordare quando la programmazione era un mestiere e il codice era elegante.
Fuzzy Logic,

0

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>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.