如何通过ViewModel控制View VisualState

时间:2015-09-27 19:17:34

标签: c# wpf xaml mvvm viewmodel

问题是:如何通过{VisualState Control获取/设置View {有两个以上的视觉状态} ViewModel MVVM模式中的{1}}(零视图代码隐藏)?

我见过类似的问题,他们的答案对我不起作用:

注意: 下面我将解释上述问题中答案的错误。如果你知道更好的方法,你可以忽略阅读这个问题的其余部分。

关于第一个问题,accepted answer的方法对我不起作用。一旦我输入提到的XAML代码

<Window .. xmlns:local="clr-namespace:mynamespace" ..>
    <TextBox Text="{Binding Path=Name, Mode=TwoWay}"
             local:StateHelper.State="{Binding Path=State, Mode=TwoWay}" />
</Window>

它显示设计时错误:The attachable property 'State' was not found in type 'StateHelper'.,我尝试通过将StateHelper.StateProperty重命名为StateHelper.State来解决此问题,最终导致两个错误。 1:The attachable property 'State' was not found in type 'StateHelper'.和 2:The local property "State" can only be applied to types that are derived from "StateHelper".

至于第二个问题,accepted answer的方法对我不起作用。将VisualStateSettingBehavior的语法错误修复为:

public class VisualStateSettingBehavior : Behavior<Control>
{

    private string sts;
    public string StateToSet
    {
        get { return sts; }
        set
        {
            sts = value;
            LoadState();
        }
    }

    void LoadState()
    {
        VisualStateManager.GoToState(AssociatedObject, sts, false);
    }
}

我在线上遇到了设计时错误

    <local:VisualStateSettingBehavior StateToSet="{Binding State}"/>

说:A 'Binding' cannot be set on the 'StateToSet' property of type 'VisualStateSettingBehavior'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.

我尝试通过使VisualStateSettingBehavior.StateToSet成为依赖属性来合并这两个解决方案,但我在View中遇到了其他设计时错误。

有什么建议吗?

1 个答案:

答案 0 :(得分:0)

最后,我可以解决这个问题。解决方案类似于first question's best answer。我发现在我的情况下,View.xaml使用附加属性存在一些限制:

  1. 必须通过DependencyProperty.RegisterAttached注册。
  2. 必须静态
  3. 必须有一个属性实例(getter / setter)。
  4. 我考虑到了this编码风格,并且最终的方法是:

    <强> VisualStateApplier

    public class VisualStateApplier
    {
    
        public static string GetVisualState(DependencyObject target)
        {
            return target.GetValue(VisualStateProperty) as string;
        }
        public static void SetVisualState(DependencyObject target, string value)
        {
            target.SetValue(VisualStateProperty, value);
        }
    
        public static readonly DependencyProperty VisualStateProperty =
            DependencyProperty.RegisterAttached("VisualState", typeof(string), typeof(VisualStateApplier), new PropertyMetadata(VisualStatePropertyChangedCallback));
    
        private static void VisualStatePropertyChangedCallback(DependencyObject target, DependencyPropertyChangedEventArgs args)
        {
            VisualStateManager.GoToElementState((FrameworkElement)target, args.NewValue as string, true); // <- for UIElements, OR:
            //VisualStateManager.GoToState((FrameworkElement)target, args.NewValue as string, true); // <- for Controls
        }
    }
    

    查看

    <!--A property inside the object that owns the states.-->
    <local:VisualStateApplier.VisualState>
        <Binding Path="State"/>
    </local:VisualStateApplier.VisualState>
    

    <强>视图模型

    private string _state;
    public string State
    {
        get { return _state; }
        set
        {
            _state = value;
            RaisePropertyChanged("State");
        }
    }