我有两个ViewModels,一个附加到主窗口,另一个附加到通过单击主窗口上的按钮打开的子窗口。子窗口包含一个项目列表,并且我想通过更新主窗口视图模型来选择项目并在主窗口中显示它。最佳实现方法是什么?谢谢!
我有两个ViewModels,一个附加到主窗口,另一个附加到通过单击主窗口上的按钮打开的子窗口。子窗口包含一个项目列表,并且我想通过更新主窗口视图模型来选择项目并在主窗口中显示它。最佳实现方法是什么?谢谢!
有很多种方法可以实现这个功能。
将主/父视图模型的引用传递给子视图模型,并让子视图模型调用主视图模型。
使子视图模型触发一个事件,由父视图模型进行订阅。
使用信使/中介者在两者之间进行通信。父视图模型进行订阅,子视图模型发布消息。这提供了松耦合。
将主视图模型设置为全局服务。以某种方式进行注册。让子视图查找服务(需要全局服务是一个非常常见的问题),然后在全局/公共接口上调用某些内容。
根据我的经验,最简单的方法是第2种方法。在子视图模型上定义一个事件。父视图模型将不得不查找子视图模型(我不知道它是否包含在其中或者您的视图模型是如何构建的)并订阅该事件。
在ViewModel之间进行通信的标准方法是使用某种形式的消息传递。其中一种很好的实现方式是MVVM Light Toolkit
以下是使用默认信使的(随机)代码:
//Registering:
Messenger.Default.Register<IEnumerable<BookViewModel>>(this, true, fillSourceWith);
Messenger.Default.Register<DisplayModeEnum>(this, ChangeMainTemplates);
//with a specific "token"
Messenger.Default.Register<object>(this, MessageTokens.ClearList, o => BookSource.Clear());
//Sending
Messenger.Default.Send<List<BookViewModel>>(newBooks);
Messenger.Default.Send<DisplayModeEnum>(DisplayModeEnum.MediumLayout);
Messenger.Default.Send<object>(null, MessageTokens.ClearList);
我几天前也遇到了同样的问题 ;-)
最终我使用了一个中介者来沟通两个视图模型。事实上,我使用了 MVVM Light 中的 Messenger。
public void Search(object parameter)
{
ChildWindow window = new ChildWindow();
SearchWindow pageSearch = new SearchWindow();
window.Content = pageSearch;
window.Show();
Messenger.Default.Register<Messages.CloseWindowMessage>(this, action => this.closeWindow(action));
}
然后,我使用主窗口所需的所有信息定义了消息:
public class CloseWindowMessage : MessageBase
{
public bool Result { get; set; }
public Model.Selected Selected { get; set; }
}
最后,从子窗口返回的消息只需使用结果和要获取的对象进行注册即可。
您应该从视图的代码后台注册以关闭窗口。
最好的方法是在子级和父级之间建立某种引用,并在关闭子级时更新此父级。
或者您可以在子级上设置某种事件,让父级监听此事件。然后在子级关闭时触发此事件。
当ViewModels在逻辑上不相关时,使用消息传递。
[抱怨]人们甚至不知道面向对象编程的基本原则吗??[/抱怨]
我认为在两个视图模型之间传递消息的最佳方式是事件编程。