¿Cómo puedo proporcionar múltiples condiciones para la activación de datos en WPF?
¿Cómo puedo proporcionar múltiples condiciones para la activación de datos en WPF?
Respuestas:
Utilice el 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: si desea tener "o", niegue todas las condiciones desde (A y B) <=> ~ (~ A o ~ B)
pero si tiene valores distintos a booleanos, intente usar convertidores de tipo:
<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>
puede usar los valores en el método Convertir de la forma que desee para producir una condición que le convenga.
conditionConverter
? ¿Cómo estamos especificando "Portland" y "OR" como nuestras dos or
opciones en este ejemplo?
Para elaborar la respuesta de @ serine e ilustrar el trabajo con una condición de valores múltiples no trivial: necesitaba mostrar una superposición de "atenuación" en un elemento para la condición booleana NOT a AND (b OR NOT c)
.
Para el fondo, esta es una pregunta de "opción múltiple". Si el usuario elige una respuesta incorrecta, se desactiva (se atenúa y no se puede volver a seleccionar). Un agente automatizado tiene la capacidad de enfocarse en cualquier opción particular para dar una explicación (borde resaltado). Cuando el agente se centra en un elemento, no debe atenuarse incluso si está desactivado . Todos los artículos que no están en centrado están marcados de-centrado , y deben ser atenuadas a cabo.
La lógica para la atenuación es así:
NOT IsFocused AND (IsDefocused OR NOT Enabled)
Para implementar esta lógica, hice un IMultiValueConverter
nombre genérico (torpemente) para que coincida con mi lógica
// '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);
}
...
}
En XAML, uso esto MultiDataTrigger
en un <Style><Style.Triggers>
recurso
<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>
Y para completar, mi convertidor se define en un 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>
ESTA RESPUESTA ES SOLO PARA ANIMACIONES
Si desea implementar la lógica AND, debe usar MultiTrigger, aquí hay un ejemplo:
supongamos que queremos hacer algunas acciones si la propiedad Text = "" (cadena vacía) AND IsKeyboardFocused = "False", entonces su código debería tener el siguiente aspecto:
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Text" Value="" />
<Condition Property="IsKeyboardFocused" Value="False" />
</MultiTrigger.Conditions>
<MultiTrigger.EnterActions>
<!-- Your actions here -->
</MultiTrigger.EnterActions>
</MultiTrigger>
Si desea implementar la lógica OR, hay un par de formas, y depende de lo que intente hacer:
La primera opción es usar múltiples disparadores.
Entonces, suponga que quiere hacer algo si Text = "" OR IsKeyboardFocused = "False",
entonces su código debería verse así:
<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>
Pero el problema en esto es ¿qué haré si quiero hacer algo si Text ISN'T null OR IsKeyboard = "True"? Esto se puede lograr con el segundo enfoque:
recuerde la regla de De Morgan, que dice! (! X &&! Y) = x || y.
Entonces lo usaremos para resolver el problema anterior, escribiendo un disparador múltiple que se dispara cuando Text = "" e IsKeyboard = "True", y haremos nuestras acciones en ACCIONES DE SALIDA , como esta:
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Text" Value="" />
<Condition Property="IsKeyboardFocused" Value="False" />
</MultiTrigger.Conditions>
<MultiTrigger.ExitActions>
<!-- Do something here -->
</MultiTrigger.ExitActions>
</MultiTrigger>