我已经开始编写我的第一个WPF / MVVM,并且正如许多其他人发现的那样,处理视图之间的导航相当混乱。
我一直在寻找一段时间,大多数主题要么推荐使用MVVM Light / PRISM,要么提出与here类似的解决方案。
我正在尝试接近MVVM导航机制,我可以直接从一个视图切换到另一个视图(不使用父窗口中的datatemplate开关)。比方说,我有一个带有主窗口的应用程序,用于加载来自不同用户控件(视图)的动态内容。
MainWindowViewModel将具有指向UserListV的CurrentV属性,以及指向UserListVM的CurrentVM属性。现在我从列表中选择一个用户,然后单击“查看”按钮,在同一窗口的另一个屏幕中查看该用户详细信息。这应该允许我切换到UserV与UserVM作为数据上下文。
我想知道在UserListVM上如何调用MainWindowViewModel来更新CurrentV和CurrentVM值,并相应地将窗口切换到UserV?
任何有关更好主意的建议都非常受欢迎!
非常感谢!
答案 0 :(得分:3)
我使用消息传递服务在ViewModel之间进行通信,同时仍然将它们分离。如果您正在使用MVVMLight,它会附带一个。我不想使用MVVM框架,而是编写自己的消息服务。以下是最近项目中的一个示例:
public class MessageService : IMessageService
{
private List<IMessageSubscription> subscribers; //list of subscription objects registered
public MessageService()
{
subscribers = new List<IMessageSubscription>();
}
public void Subscribe<T>(string message, Action<T> action)
{
subscribers.Add(new MessageSubscription<T>()
{
Message = message,
MessageActionWithArgs = action
});
}
public void Subscribe(string message, Action action)
{
subscribers.Add(new MessageSubscription<bool>()
{
Message = message,
MessageActionNoArgs = action
});
}
public void Send<T>(string message, T args)
{
IEnumerable<IMessageSubscription> matches = subscribers.Where(x => x.Message == message && x.PayLoadType == typeof(T));
foreach (IMessageSubscription sub in matches.ToList())
{
sub.InvokeMessageAction((T)args);
}
}
public void Send(string message)
{
IEnumerable<IMessageSubscription> matches = subscribers.Where(x => x.Message == message);
foreach (IMessageSubscription sub in matches.ToList())
{
sub.InvokeMessageAction();
}
}
}
因此,例如,MainViewModel将侦听诸如“ActiveViewModelChangeRequest”之类的消息,而其他视图模型将在需要变为活动时发送该消息。所以,在MainViewModel中你会有这样的东西:
public MainViewModel()
{
messageService.Register<ViewModelBase>("ActiveViewModelChangeRequest", UpdateActiveViewModel);
}
private void UpdateActiveViewModel(ViewModelBase viewModel)
{
this.CurrentVM = viewModel;
}
然后在UserListVM中你会得到:
private void OnUserSelect(object sender, UserSelectionEventArgs e)
{
UserVM viewModel = new UserVM(SelectedUser);
messageService.Send<ViewModelBase>("ActiveViewModelChangeRequest, viewModel);
}
MVVM应用程序的messenger模式上有很多可用的阅读材料。我建议你阅读这篇文章。