Gibt es in WPF eine einfache Möglichkeit, VisualStates an Enumerationswerte zu binden? Ein bisschen wie DataStateBehavior, aber für ein Enum?DataStateBehavior für Enum statt Bool? Schnur?
Antwort
Der beste Weg ist, einfach weiter gehen und ein Verhalten zu implementieren, die genau das tut -
public class EnumStateBehavior : Behavior<FrameworkElement>
{
public object EnumProperty
{
get { return (object)GetValue(EnumPropertyProperty); }
set { SetValue(EnumPropertyProperty, value); }
}
// Using a DependencyProperty as the backing store for EnumProperty. This enables animation, styling, binding, etc...
public static readonly DependencyProperty EnumPropertyProperty =
DependencyProperty.Register("EnumProperty", typeof(object), typeof(EnumStateBehavior), new UIPropertyMetadata(null, EnumPropertyChanged));
static void EnumPropertyChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (e.NewValue == null) return;
EnumStateBehavior eb = sender as EnumStateBehavior;
VisualStateManager.GoToElementState(eb.AssociatedObject, e.NewValue.ToString(), true);
}
}
Die Nutzung ist denkbar einfach - Verwendung wie folgt:
<i:Interaction.Behaviors>
<local:EnumStateBehavior EnumProperty="{Binding MyEnumProperty}" />
</i:Interaction.Behaviors>
Es gibt eine DataStateSwitchBehavior in SL, das zu WPF portiert werden konnte: Anyone have a DataStateSwitchBehavior for WPF4?
die Syntax ist ziemlich einfach:
Sie können dies in reinem XAML tun, indem Sie einen DataTrigger pro möglichem Enum-Wert verwenden, wobei jeder Trigger GoToStateAction mit einem anderen Status aufruft. Siehe das Beispiel unten. Für weitere Details werfen Sie einen Blick auf Enum driving a Visual State change via the ViewModel.
<i:Interaction.Triggers>
<ei:DataTrigger Binding="{Binding ConfirmedAnswerStatus}" Value="Unanswered">
<ei:GoToStateAction StateName="UnansweredState" UseTransitions="False" />
</ei:DataTrigger>
<ei:DataTrigger Binding="{Binding ConfirmedAnswerStatus}" Value="Correct">
<ei:GoToStateAction StateName="CorrectlyAnsweredState" UseTransitions="True" />
</ei:DataTrigger>
<ei:DataTrigger Binding="{Binding ConfirmedAnswerStatus}" Value="Incorrect">
<ei:GoToStateAction StateName="IncorrectlyAnsweredState" UseTransitions="True" />
</ei:DataTrigger>
</i:Interaction.Triggers>
Dies ist tatsächlich, was ich für die meisten Dinge getan habe. – Firoso
Ich hatte Probleme mit der obigen EnumStateBehavior Antwort.
Der PropertyChanged-Handler wird zuerst ausgelöst, wenn das AssociatedObject null ist (da die Bindung eingerichtet wurde, aber das Verhalten noch nicht angefügt wurde). Auch wenn das Verhalten zum ersten Mal angefügt wird, sind die Zielelemente der VisualState-Animation möglicherweise noch nicht vorhanden, da das Verhalten möglicherweise vor anderen untergeordneten visuellen Bäumen angehängt wurde.
Die Lösung bestand darin, das Loaded-Ereignis für das zugeordnete Objekt zu verwenden, um sicherzustellen, dass der Anfangszustand der Bindung festgelegt ist.
public class EnumStateBehavior : Behavior<FrameworkElement>
{
public static readonly DependencyProperty BindingProperty =
DependencyProperty.Register(nameof(Binding), typeof(object), typeof(EnumStateBehavior), new UIPropertyMetadata(null, BindingPropertyChanged));
public object Binding
{
get { return (object)GetValue(BindingProperty); }
set { SetValue(BindingProperty, value); }
}
protected override void OnAttached()
{
base.OnAttached();
this.AssociatedObject.Loaded += AssociatedObject_Loaded;
}
protected override void OnDetaching()
{
this.AssociatedObject.Loaded -= AssociatedObject_Loaded;
base.OnDetaching();
}
private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
{
if (Binding != null)
GoToState();
}
private void GoToState()
{
VisualStateManager.GoToElementState(this.AssociatedObject, Binding.ToString(), true);
}
private static void BindingPropertyChanged(object sender, DependencyPropertyChangedEventArgs e)
{
var eb = (EnumStateBehavior)sender;
if (e.NewValue == null || eb.AssociatedObject == null || !eb.AssociatedObject.IsLoaded)
return;
eb.GoToState();
}
}
Ich glaube, Sie die Überschreibung auslassen können ... und im Wesentlichen würde dies nicht einmal ein Verhalten –
@Markus in Bezug auf die Überschreibung, du hast Recht sein muß. Was das Verhalten angeht - ich denke, das könnte eine angehängte Eigenschaft sein, aber so ist es - (A) verwendbar von Blend, und (B) kann erzwungen werden, nur auf FrameworkElement gesetzt zu werden. –
funktioniert gut, danke! – thumbmunkeys