问题是:如何在 MVVM 模式(使用零视图代码隐藏(中通过我的ViewModel
获取/设置View
上Control
(具有两个以上的视觉状态(的VisualState
?
见过类似的问题,他们的答案对我不起作用:
- 将 [VisualStateManager] 视图状态绑定到 MVVM 视图模型?
- 如何通过视图模型更改视觉状态
注意:下面我将解释上述问题中的答案出了什么问题。如果您知道更好的方法,则可以忽略阅读此问题的其余部分。
至于第一个问题,接受的答案的方法对我不起作用。一旦我键入提到的 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".
至于第二个问题,接受的答案的方法对我不起作用。修复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
中出现了其他设计时错误。
有什么建议吗?
终于,我可以解决这个问题了。解决方案类似于第一个问题的最佳答案。我发现在我的情况下,使用附加属性View.xaml
有一些限制:
- 它必须通过
DependencyProperty.RegisterAttached
注册。 - 它必须是静态的。
- 它必须有一个属性实例(getter/setter(。
我带着这种编码风格完成了它,最后的方法是:
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");
}
}