如何通过ViewModel控制View VisualState

How to control View VisualState through ViewModel

问题是:如何在View 通过我的 ViewModel 在 MVVM 模式中(使用零视图代码隐藏)?

我看过类似的问题但答案对我不起作用:

注意: 下面我将解释上述问题的答案有什么问题。如果您知道更好的方法,则可以不阅读此问题的其余部分。

关于第一个问题,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.

中遇到了其他设计时错误

有什么建议吗?

我终于解决了这个问题。该解决方案类似于 first question's best answer。我发现在我的情况下 View.xaml 使用附加的 属性:

有一些限制
  1. 必须通过DependencyProperty.RegisterAttached注册。
  2. 必须是静态
  3. 它必须有一个 属性 实例 (getter/setter)。

我在考虑 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>

ViewModel:

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