Wpf Enum而不是bool的DataStateBehavior?一串

Wpf Enum而不是bool的DataStateBehavior?一串,wpf,data-binding,behavior,Wpf,Data Binding,Behavior,WPF中是否有一种简单的方法可以将VisualState绑定到枚举值?有点像DataStateBehavior,但对于Enum?最好的方法是继续执行并实现一个行为,该行为可以实现- public class EnumStateBehavior : Behavior<FrameworkElement> { public object EnumProperty { get { return (object)GetValue(EnumPropertyProp

WPF中是否有一种简单的方法可以将VisualState绑定到枚举值?有点像DataStateBehavior,但对于Enum?

最好的方法是继续执行并实现一个行为,该行为可以实现-

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);
    }

}
公共类EnumStateBehavior:行为
{
公共对象枚举属性
{
get{return(object)GetValue(EnumPropertyProperty);}
set{SetValue(EnumPropertyProperty,value);}
}
//使用DependencyProperty作为EnumProperty的备份存储。这将启用动画、样式设置、绑定等。。。
公共静态只读从属属性EnumPropertyProperty属性=
Register(“EnumProperty”、typeof(object)、typeof(EnumStateBehavior)、新UIPropertyMetadata(null、EnumPropertyChanged));
静态无效EnumPropertyChanged(对象发送方,DependencyPropertyChangedEventArgs e)
{
if(e.NewValue==null)返回;
EnumStateBehavior eb=发送方作为EnumStateBehavior;
VisualStateManager.GoToElementState(eb.AssociatedObject,e.NewValue.ToString(),true);
}
}
用法非常简单-使用方法如下:

<i:Interaction.Behaviors>
        <local:EnumStateBehavior EnumProperty="{Binding MyEnumProperty}" />
</i:Interaction.Behaviors>

SL中存在一个可以移植到WPF的DataStateSwitchBehavior:

语法非常简单:

 <is:DataStateSwitchBehavior Binding="{Binding Orientation}">
     <is:DataStateSwitchCase Value="Left" State="LeftState"/>
     <is:DataStateSwitchCase Value="Right" State="RightState"/>
     <is:DataStateSwitchCase Value="Down" State="DownState"/>
     <is:DataStateSwitchCase Value="Up" State="UpState"/>
 <is:DataStateSwitchCase/>

您可以在纯xaml中使用DataTrigger per可能的枚举值,每个触发器使用不同的状态调用GoToStateTAction。请参见下面的示例。有关更多详细信息,请参阅


我对上述EnumStateBehavior答案有疑问

当AssociatedObject为null时,PropertyChanged处理程序将首先触发(因为绑定已设置,但行为尚未附加)。此外,即使在第一次附加该行为时,VisualState动画的目标元素也可能不存在,因为该行为可能已在其他子视觉树之前附加

解决方案是在关联对象上使用加载的事件来确保绑定的初始状态已设置

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();
    }
}
公共类EnumStateBehavior:行为
{
公共静态只读DependencyProperty BindingProperty=
Register(nameof(Binding)、typeof(object)、typeof(EnumStateBehavior)、新UIPropertyMetadata(null、BindingPropertyChanged));
公共对象绑定
{
获取{return(object)GetValue(BindingProperty);}
set{SetValue(BindingProperty,value);}
}
受保护的覆盖无效附加()
{
base.onatached();
this.AssociatedObject.Loaded+=AssociatedObject\u Loaded;
}
附加时受保护的覆盖无效()
{
this.AssociatedObject.Loaded-=AssociatedObject\u Loaded;
base.OnDetaching();
}
已加载关联对象的私有无效(对象发送方,路由目标)
{
if(绑定!=null)
GoToState();
}
私有void GoToState()
{
VisualStateManager.GoToElementState(this.AssociatedObject,Binding.ToString(),true);
}
私有静态void BindingPropertyChanged(对象发送方,DependencyPropertyChangedEventArgs e)
{
var eb=(EnumStateBehavior)发送方;
如果(e.NewValue==null | | eb.AssociatedObject==null | |!eb.AssociatedObject.IsLoaded)
返回;
eb.GoToState();
}
}

我想您可以省去覆盖。。。从本质上讲,这甚至不需要是一个Behaviour@Markus至于超控,你是对的。至于行为-我猜这可能是一个附加属性,但这样它可以-(A)从Blend中可用,并且(B)可以强制只放在FrameworkElement上否则您可能会得到一个非信息性的
NullReferenceException
。这实际上是我最后做的大多数事情。
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();
    }
}