如何通过ViewModel控制View VisualState
How to control View VisualState through ViewModel
问题是:如何在View
通过我的 ViewModel
在 MVVM 模式中(使用零视图代码隐藏)?
我看过类似的问题但答案对我不起作用:
- Binding [VisualStateManager] view state to a MVVM viewmodel?
- How to change VisualState via ViewModel
注意: 下面我将解释上述问题的答案有什么问题。如果您知道更好的方法,则可以不阅读此问题的其余部分。
关于第一个问题,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
使用附加的 属性:
有一些限制
- 必须通过
DependencyProperty.RegisterAttached
注册。
- 必须是静态。
- 它必须有一个 属性 实例 (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");
}
}
问题是:如何在View
通过我的 ViewModel
在 MVVM 模式中(使用零视图代码隐藏)?
我看过类似的问题但答案对我不起作用:
- Binding [VisualStateManager] view state to a MVVM viewmodel?
- How to change VisualState via ViewModel
注意: 下面我将解释上述问题的答案有什么问题。如果您知道更好的方法,则可以不阅读此问题的其余部分。
关于第一个问题,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
使用附加的 属性:
- 必须通过
DependencyProperty.RegisterAttached
注册。 - 必须是静态。
- 它必须有一个 属性 实例 (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");
}
}