如何通过ViewModel更改VisualState

4
我知道这个问题和许多问题类似。但无论如何,我不理解。
我有几个VisualStates(超过2个,因此DataStateBehavior不是我的解决方案)。我有一个ViewModel,它有一个枚举属性CurrentState。每个枚举值代表一个状态,也可以有几个枚举值表示一个状态,没有关系。当CurrentState更改时,我希望VisualState也会更改(我认为:绑定正是为了这种情况而创建的!)。
我能将CurrentState与视图VisualState绑定(仅限XAML解决方案),以获得上述行为吗?
如果可以,我该如何做?
如果不行,我应该如何在我的ViewModel中使用VisualStateManager.GoToState()方法?
2个回答

9

我想提供一个类似于@FasterSolutions解决方案的解决方案,使用Blend SDK的内置组件。

在视图模型的“CurrentState”属性上设置PropertyChangedTrigger,并添加GoToStateAction来更改可视状态:

<i:Interaction.Triggers
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Inte‌​ractivity"  
    xmlns:ei="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microso‌ft.Expression.Interactions">
    <ei:PropertyChangedTrigger Binding="{Binding CurrentState}">
        <ei:GoToStateAction StateName="{Binding CurrentState}" />
    </ei:PropertyChangedTrigger>
</i:Interaction.Triggers>

5
针对那些找不到 e 和 ei 的人, xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" xmlns:ei="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions" 可能会有帮助。 - Ankit
@ay89 谢谢,已添加在上面。 - McGarnagle
3
这些xmlns在VS2015中可用,并且应该这样使用:xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" - Drew Noakes

8
我不建议在ViewModel中使用VisualStateManager.GoToState,原因有很多,最重要的是你必须传递要更改其可视状态的控件。将UI控件传递给ViewModel违背了整个MVVM方法论。

我的建议是(适用于Windows 8 Store)使用Winrt Behaviours或使用Blend system.windows.interactivity.dll(具有相同功能)从ViewModel中获取VisualState名称并更新对象。代码看起来应该像这样:

ViewModel:

public string State{
    get{_stateName;}
    set{_stateName=value;
        RaisePropertyChanged("State");
}

查看:

<Grid>
    <I:Interaction.Behaviors>
        <b:VisualStateSettingBehavior StateToSet="{Binding State}"/>
    </i:Interaction.Behaviors>
</Grid>

行为:

public class VisualStateSettingBehavior:Behavior<Control>
{

    StateToSet{
               get{GetValue(StateProperty) as string;}
               set{SetValue{StateProperty,value);
                    LoadState();}
}
private void LoadState()
{
VisualStateManager.GoToState(AssociatedObject,StateToSet,true);
}
}

这个行为是连接控件并以编程方式扩展其功能。这种方法允许您将ViewModel与View分开。


1
你使用哪个命名空间来获取VisualStateSettingBehavior的“b”? - JonasN89

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接