在 ViewModel (MVVM) 中使用视图方法

Posted

技术标签:

【中文标题】在 ViewModel (MVVM) 中使用视图方法【英文标题】:Using view method inside ViewModel (MVVM) 【发布时间】:2014-08-18 21:45:21 【问题描述】:

假设我正在使用 FlowDocumentPageViewer,并且我想使用 find 方法。 如何在遵循 MVVM 规则的同时使用它?我做了一些搜索,似乎解决方案是混合的。

有人建议你把View聚合到ViewModel,然后用它来调用需要的方法:

例如:

private MainWindow mw; 

public MainWindowViewModel(MainWindow mw)

    this.mw = mw;


public void Find()

    mw.flowDocument.find();

但其他人建议在视图中使用这些方法(代码隐藏)是可以的,因为 ViewModel 不应该调用视图特定的方法。

最后,我听说过使用附加行为来解决这个问题,但我没有深入研究过该方法是否合适。

我真的不知道哪种方法是正确的,或者如果所有这些方法都不正确,如何处理这种情况。如果您能给我一些关于首选哪种方法以及原因的见解,我将不胜感激。

提前感谢您的回答。

【问题讨论】:

好吧,在这里真正帮助您:您打算如何调用该方法?它是绑定在按钮上的吗?然后使用命令。它是基于 PropertyChanged 事件自动执行的吗?然后只需从属性的 ViewModel 中调用它。如果您愿意,请提供有关整体解决方案的更多信息。 @Xcalibur37 不,它没有绑定到按钮。这是一种与名为 find 的视图相关联的方法。它是 FlowDocumentPageViewer 的一部分。 重复***.com/questions/25310867/… 【参考方案1】:

我会用 MVVMLight 消息传递 之类的方法来解决这个问题。 (从您发送消息的 Viewmodel 并在您后面的 View 代码上注册此消息。)

Microsoft 的 Jesse Liberty 有 a great tutorial 介绍如何利用 MVVM Light 中的消息传递。

充当消息类型的类:

public class FlowDocumentFindMessage

   public string PageName  get; private set; 
   // or some other properties go here

   FlowDocumentFindMessage(string pageName)
          this.PageName = pageName
   

新的 Find,发送消息

public void Find()

    var msg = new FlowDocumentFindMessage("Page");
    Messenger.Default.Send<FlowDocumentFindMessage>( msg );

代码隐藏,用于注册新消息

Messenger.Default.Register<GoToPageMessage>( this, ( action ) => ReceiveMessage( action ));

private object ReceiveMessage( FlowDocumentFindMessage action )

    //do some stuff

【讨论】:

感谢您的帮助! 这是一个很好的 View 和 ViewModel 解耦。不过有几点需要注意:1. 在视图注册之前仔细检查不发送消息,如果您的逻辑依赖于它,您可能会遇到不可预测的状态 2. 在控件 IsLoaded 之前仔细检查您的控件是否支持消息处理程序逻辑,您如果提前调用可能会出现异常如果您在 Loaded 事件或 ViewModel 创建场景中发送消息,请考虑这些,否则您很高兴。

以上是关于在 ViewModel (MVVM) 中使用视图方法的主要内容,如果未能解决你的问题,请参考以下文章

WPF(MVVM):从 Viewmodel 关闭视图?

如何将相同的viewmodel设置为xamarin表单中的新mvvm中的两个视图

如何在 viewmodel 中访问 mvvm 模型中的控件?

MVVM + WPF - 为具有多个视图的 ViewModel 设计

MVVM:GUI 和 ViewModel 之间的真正分离

具有可观察集合类型的 Viewmodel 的 MVVM ListView 不更新视图