将[VisualStateManager]视图状态绑定到MVVM视图模型?

aL3*_*891 30 silverlight wpf xaml mvvm visualstatemanager

如何将控件的VisualStateManager状态绑定到viewmodel中的属性?可以吗?

aL3*_*891 30

其实你可以.诀窍是创建一个Attached属性并添加一个实际调用的属性更改回调GoToState:

public class StateHelper {
    public static readonly DependencyProperty StateProperty = DependencyProperty.RegisterAttached( 
        "State", 
        typeof( String ), 
        typeof( StateHelper ),
        new UIPropertyMetadata( null, StateChanged ) );

      internal static void StateChanged( DependencyObject target, DependencyPropertyChangedEventArgs args ) {
      if( args.NewValue != null )
        VisualStateManager.GoToState( ( FrameworkElement )target, args.NewValue, true );
    }
  }
Run Code Online (Sandbox Code Playgroud)

然后,您可以在xaml中设置此属性,并像查看其他任何内容一样为viewmodel添加绑定:

<Window .. xmlns:local="clr-namespace:mynamespace" ..>
    <TextBox Text="{Binding Path=Name, Mode=TwoWay}"
             local:StateHelper.State="{Binding Path=State, Mode=TwoWay}" />
</Window>
Run Code Online (Sandbox Code Playgroud)

Name并且State是viewmodel中的常规属性.当Name在视图模型中设置时,无论是通过绑定还是其他东西,它都可以更改State女巫将更新视觉状态.State也可以由任何其他因素设置,但它仍然会更新文本框上的视图状态.

由于我们使用普通绑定绑定到Status,我们可以应用转换器或我们通常能够执行的任何其他操作,因此viewmodel不必知道它实际上设置了可视状态名称State可能是一个布尔或一个枚举或其他什么.

您也可以在.net 3.5上使用wpftoolkit使用此方法,但您必须转换target为a Control而不是FrameworkElement.

关于视觉状态的另一个快速注释,确保你没有命名你的视觉状态,以便它们与内置状态冲突,除非你知道你正在做什么.对于验证尤其如此,因为验证引擎将在每次更新绑定时尝试设置其状态(以及在某些其他时间也是如此).到这里获取有关不同控件的可视状态名称的参考.

  • 我发现。1:StateHelper必须继承DependencyObject。2:UIPropertyMetadata在WinRT中被命名为PropertyMetadata。3:将属性附加到Page或UserControl的第一个&lt;Grid&gt;元素,而不是Page或UserControl本身。 (2认同)

小智 28

我是WPF的新手,但是经过一段时间以奇怪的方式通过MVVM层扭曲状态后我终于找到了一个我很满意的解决方案.将状态更改为ViewModel逻辑的一部分,并在XAML视图中侦听它.不需要"桥接"方法或类似背后的转换器或代码.

查看构造函数背后的代码

// Set ViewModel as the views DataContext
public ExampleView(ExampleViewModel vm)
{
  InitializeComponent();
  DataContext = vm;
}
Run Code Online (Sandbox Code Playgroud)

XAML命名空间

// Reference expression namespaces
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
Run Code Online (Sandbox Code Playgroud)

XAML绑定

// Bind GoToStateAction directly to a ViewModel property
<i:Interaction.Triggers>
  <ei:DataTrigger Binding="{Binding State}" Value="{Binding State}">
    <ei:GoToStateAction StateName="{Binding State}" />
  </ei:DataTrigger>
</i:Interaction.Triggers>
Run Code Online (Sandbox Code Playgroud)

ViewModel代码

// Update property as usual
private string _state;
public string State
{
  get { return _state; }
  set
  {
    _state = value;
    NotifyPropertyChanged("State");
  }
}
Run Code Online (Sandbox Code Playgroud)

现在设置ExampleViewModel的State属性将在视图中触发相应的状态更改.确保可视状态具有与State属性值对应的名称,或者使用枚举,转换器等使其复杂化.


Tow*_*own 11

阅读本文:Silverlight 4:使用VisualStateManager将状态动画与MVVM结合使用

或者,如果您刚刚在两种状态之间切换,则可以使用DataStateBehaviour.我在显示登录页面时使用它来切换背景.

命名空间

xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" 
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
Run Code Online (Sandbox Code Playgroud)

XAML

<i:Interaction.Behaviors>
   <ei:DataStateBehavior TrueState="LoginPage" FalseState="DefaultPage" 
                         Binding="{Binding IsLoginPage}" Value="true" />
</i:Interaction.Behaviors>
Run Code Online (Sandbox Code Playgroud)

通过使用诸如Caliburn.Micro之类的框架,这变得更加简单.