从 ViewModel 触发 UIElement 的操作
Triggering an action of a UIElement from a ViewModel
我已经实现了 Wiesław Šoltés' awesome ZoomBorder,但我在 WPF 和 MVVM 方面遇到了一些困难。为了问题的完整性,ZoomBorder
是从 Border
继承的 UIElement
,并为用户提供了缩放和平移继承边框内容的可能性。它还具有重置缩放和平移的能力。
我想让 ZoomBorder
对某个视图模型发布的事件做出反应,以便在发布该事件时,ZoomBorder
重置缩放。在我的实现中,ZoomBorder
的 DataContext
是一个 ContentViewModel
,它有一个通过 Autofac 注入的 IEventAggregator
(Prism.Events)。理想情况下,我希望将事件聚合器直接注入 ZoomBorder
,以便它可以订阅事件,但我不能,因为构造函数需要无参数。
所以 ContentViewModel
必须订阅该事件,但我如何从 ContentViewModel
调用 ZoomBorder
的 Reset
方法?我知道我会违反 MVVM,但我不知道该怎么做。我考虑过让 ZoomBorder
通过依赖项 属性 公开 Command
,但是 Reset
代码必须在视图模型上,但它不能。
您可以在视图或控件中使用 ServiceLocator
来解析容器中的类型。
public ZoomBorder()
{
_eventAggregator = ServiceLocator.Current.GetInstance<IEventAggregator>();
}
如果您在没有 Prism 的情况下使用 AutoFac 和事件聚合器,则可以使用包 Autofac.Extras.CommonServiceLocator
和 register your container 到 ServiceLocator
。
var builder = new ContainerBuilder();
var container = builder.Build();
var csl = new AutofacServiceLocator(container);
ServiceLocator.SetLocatorProvider(() => csl);
我会使用绑定。
向 Zoomborder 添加依赖项 属性。
public bool? ResetZoom
{
get
{
return (bool?)GetValue(ResetZoomProperty);
}
set
{
SetValue(ResetZoomProperty, value);
}
}
public static readonly DependencyProperty ResetZoomProperty =
DependencyProperty.Register("ResetZoom",
typeof(bool?),
typeof(CloseMe),
new PropertyMetadata(null, new PropertyChangedCallback(ResetZoomChanged)));
private static void ResetZoomChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if ((bool?)e.NewValue != true)
{
return;
}
ZoomBorder zb = (ZoomBorder)d;
zb.Reset();
zb.SetCurrentValue(ResetZoomProperty, false);
}
然后您可以将其绑定到 ContentViewModel 中的 public bool 属性。
当设置为 true 时,边框将重置。
此视频展示了如何从 Views/UI 组件创建抽象并使用接口从 VM 调用它们的方法。不要让标题骗了你。这看起来很适合这个场景
“如何在 C# 中从 ViewModel 关闭 Windows”
除了在 window 上调用 Close 方法外,您还可以调整它以从 VM 调用控件上的 Reset 方法。
我已经实现了 Wiesław Šoltés' awesome ZoomBorder,但我在 WPF 和 MVVM 方面遇到了一些困难。为了问题的完整性,ZoomBorder
是从 Border
继承的 UIElement
,并为用户提供了缩放和平移继承边框内容的可能性。它还具有重置缩放和平移的能力。
我想让 ZoomBorder
对某个视图模型发布的事件做出反应,以便在发布该事件时,ZoomBorder
重置缩放。在我的实现中,ZoomBorder
的 DataContext
是一个 ContentViewModel
,它有一个通过 Autofac 注入的 IEventAggregator
(Prism.Events)。理想情况下,我希望将事件聚合器直接注入 ZoomBorder
,以便它可以订阅事件,但我不能,因为构造函数需要无参数。
所以 ContentViewModel
必须订阅该事件,但我如何从 ContentViewModel
调用 ZoomBorder
的 Reset
方法?我知道我会违反 MVVM,但我不知道该怎么做。我考虑过让 ZoomBorder
通过依赖项 属性 公开 Command
,但是 Reset
代码必须在视图模型上,但它不能。
您可以在视图或控件中使用 ServiceLocator
来解析容器中的类型。
public ZoomBorder()
{
_eventAggregator = ServiceLocator.Current.GetInstance<IEventAggregator>();
}
如果您在没有 Prism 的情况下使用 AutoFac 和事件聚合器,则可以使用包 Autofac.Extras.CommonServiceLocator
和 register your container 到 ServiceLocator
。
var builder = new ContainerBuilder();
var container = builder.Build();
var csl = new AutofacServiceLocator(container);
ServiceLocator.SetLocatorProvider(() => csl);
我会使用绑定。
向 Zoomborder 添加依赖项 属性。
public bool? ResetZoom
{
get
{
return (bool?)GetValue(ResetZoomProperty);
}
set
{
SetValue(ResetZoomProperty, value);
}
}
public static readonly DependencyProperty ResetZoomProperty =
DependencyProperty.Register("ResetZoom",
typeof(bool?),
typeof(CloseMe),
new PropertyMetadata(null, new PropertyChangedCallback(ResetZoomChanged)));
private static void ResetZoomChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if ((bool?)e.NewValue != true)
{
return;
}
ZoomBorder zb = (ZoomBorder)d;
zb.Reset();
zb.SetCurrentValue(ResetZoomProperty, false);
}
然后您可以将其绑定到 ContentViewModel 中的 public bool 属性。
当设置为 true 时,边框将重置。
此视频展示了如何从 Views/UI 组件创建抽象并使用接口从 VM 调用它们的方法。不要让标题骗了你。这看起来很适合这个场景
“如何在 C# 中从 ViewModel 关闭 Windows”
除了在 window 上调用 Close 方法外,您还可以调整它以从 VM 调用控件上的 Reset 方法。