如何使用MVVM模式从ViewModel调用View中的函数(可与UIElements一起使用)



我使用的是MVVM Light Toolkit,在我的View中,我有一个函数可以获取屏幕截图并返回该屏幕截图的字节数组。由于截屏(使用UIElement s)与视图而非ViewModel有关。

byte[] TakeScreenShot(Canvas sourceUiElement)    

我需要在ViewModel中获得函数的返回值,但我无法想出正确的方法。

另一方面,如果我想把这个函数移到我的ViewModel中,我需要访问视图中的那个元素,但不引用ViewModel中的view(可能是作为参数或Command?的东西)

由于此问题被标记为MvvmLight,因此下面是MvvmLightToolkit的答案。使用上述工具箱的Messenger类。只需在应用程序中的某个位置定义以下消息类:

public class TakeScreenshotMessage : MessageBase { }
public class ScreenshotTakenMessage : GenericMessage<byte[]>
{
    public ScreenshotTakenMessage (byte[]content) : base(content) { }
    public ScreenshotTakenMessage (object sender, byte[]content) : base(sender, content) { }
    public ScreenshotTakenMessage (object sender, object target, byte[]content) : base(sender, target, content) { }
}

在代码隐藏的构造函数中,注册TakeScreenshotMessage,如下所示:

Messenger.Default.Register<TakeScreenshotMessage>(this, (msg) =>
{
    byte[] bytes = this.TakeScreenShot(someCanvas);
    Messenger.Default.Send(new ScreenshotTakenMessage(bytes));
});

在您的视图模型中,注册ScreenshotTakeMessage,如下所示:

Messenger.Default.Register<ScreenshotTakenMessage>(this, (msg) =>
{
    byte[] bytes = msg.Content.
    //do something with your bytes
});

现在,只需从应用程序中的任何位置调用以下命令(即视图模型、视图、辅助类等),您就可以随时进行屏幕截图:

Messenger.Default.Send(new TakeScreenshotMessage());

我会将TakeScreenShot与按钮的点击事件或代码后面的东西绑定,在ViewModel上有一个名为Snapshot的属性,例如,在点击事件中,您获得byte[]数组,将其分配给ViewModel的属性Snapshot,就像代码后面一样。

public void ButtonOnClick(object sender, EventArgs e)
{
    var myViewModel = this.DataContext;
    myViewModel.Snapshot = this.TakeScreenShot(someCanvas);
}

取决于你对MVVM的严格程度,有些人可能不同意,我认为你的视图引用你的视图模型是完全有效的,也就是说,你必须知道你绑定到的上下文,但不能反过来。这就像手动绑定到我。

最新更新