【问题标题】:How to call a function(which works with UIElements) in View from ViewModel using MVVM pattern如何使用 MVVM 模式从 ViewModel 调用 View 中的函数(与 UIElements 一起使用)
【发布时间】:2012-09-02 15:44:37
【问题描述】:

我正在使用 MVVM Light Toolkit,在我的视图中,我有一个函数可以截取屏幕截图并返回该屏幕截图的字节数组。由于截图(使用UIElements)与视图相关,而不是视图模型。

byte[] TakeScreenShot(Canvas sourceUiElement)    

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

另一方面,如果我想将此函数移动到我的 ViewModel,我需要访问视图中的该元素,但不引用我的 ViewModel 中的视图(可能作为 Command 的参数或其他内容?)

【问题讨论】:

  • 您建议的编辑应该针对您的问题,而不是答案。
  • 我想完成答案,看来我需要阅读常见问题页面!

标签: mvvm view viewmodel screenshot mvvm-light


【解决方案1】:

由于这个问题被标记为 MvvmLight,那么这里是一个 MvvmLight Toolkit 答案。使用所述工具包的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));
});

在您的视图模型中,像这样注册 ScreenshotTakenMessage:

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

现在您可以随时从应用程序中的任何位置(即视图模型、视图、助手类等)调用以下命令来截取屏幕截图:

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

【讨论】:

  • 这比我们以前做的更性感!
  • @Sabgard - Send 和 Register 方法也被重载以采用可以是任何对象的 Token 参数(即我通常只使用常量字符串)。通过使用 Token 参数,您可以在应用程序的各个部分注册相同的消息类,但限制哪些侦听器实际接收消息。一种密码,如果你愿意的话。这是我提出的一个问题中的example
  • 我对 MVVM Light 中的 Messegers 很熟悉,但我从未想过我可以在我的视图中使用它们。
【解决方案2】:

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

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

取决于您对 MVVM 的严格程度,有些人可能不同意,我认为您的视图引用您的视图模型是完全有效的,也就是说,无论如何您都必须知道要绑定到的上下文,但反之则不然。就像手动绑定我一样。

【讨论】:

  • @Joshscrop 我需要从 ViewModel 调用该函数,但是按照您建议的方式,该函数是从 View 调用的,尽管如果我能找到一种巧妙的方法来从 ViewModel 通知 View问题解决了。
  • 你总是可以有一个隐藏的复选框来绑定到视图模型上的一个属性,比如 ActivateProperty。在视图上,您​​可以订阅复选框的 checkedchange 事件,并从那里执行上述代码。
  • 是的,这就是我所做的,但有点不同!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-17
  • 2014-04-11
  • 1970-01-01
  • 2013-05-31
  • 1970-01-01
  • 2020-11-12
相关资源
最近更新 更多