从 ViewModel 触发 UIElement 的操作

Triggering an action of a UIElement from a ViewModel

我已经实现了 Wiesław Šoltés' awesome ZoomBorder,但我在 WPF 和 MVVM 方面遇到了一些困难。为了问题的完整性,ZoomBorder 是从 Border 继承的 UIElement,并为用户提供了缩放和平移继承边框内容的可能性。它还具有重置缩放和平移的能力。

我想让 ZoomBorder 对某个视图模型发布的事件做出反应,以便在发布该事件时,ZoomBorder 重置缩放。在我的实现中,ZoomBorderDataContext 是一个 ContentViewModel,它有一个通过 Autofac 注入的 IEventAggregator (Prism.Events)。理想情况下,我希望将事件聚合器直接注入 ZoomBorder,以便它可以订阅事件,但我不能,因为构造函数需要无参数。

所以 ContentViewModel 必须订阅该事件,但我如何从 ContentViewModel 调用 ZoomBorderReset 方法?我知道我会违反 MVVM,但我不知道该怎么做。我考虑过让 ZoomBorder 通过依赖项 属性 公开 Command,但是 Reset 代码必须在视图模型上,但它不能。

您可以在视图或控件中使用 ServiceLocator 来解析容器中的类型。

public ZoomBorder()
{
   _eventAggregator = ServiceLocator.Current.GetInstance<IEventAggregator>();
}

如果您在没有 Prism 的情况下使用 AutoFac 和事件聚合器,则可以使用包 Autofac.Extras.CommonServiceLocatorregister your containerServiceLocator

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”

https://youtu.be/U7Qclpe2joo

除了在 window 上调用 Close 方法外,您还可以调整它以从 VM 调用控件上的 Reset 方法。