使用直接ViewModel切换的WPF / MVVM导航

时间:2015-12-30 15:30:25

标签: wpf mvvm navigation

我已经开始编写我的第一个WPF / MVVM,并且正如许多其他人发现的那样,处理视图之间的导航相当混乱。

我一直在寻找一段时间,大多数主题要么推荐使用MVVM Light / PRISM,要么提出与here类似的解决方案。

我正在尝试接近MVVM导航机制,我可以直接从一个视图切换到另一个视图(不使用父窗口中的datatemplate开关)。比方说,我有一个带有主窗口的应用程序,用于加载来自不同用户控件(视图)的动态内容。

MainWindowViewModel将具有指向UserListV的CurrentV属性,以及指向UserListVM的CurrentVM属性。现在我从列表中选择一个用户,然后单击“查看”按钮,在同一窗口的另一个屏幕中查看该用户详细信息。这应该允许我切换到UserV与UserVM作为数据上下文。

我想知道在UserListVM上如何调用MainWindowViewModel来更新CurrentV和CurrentVM值,并相应地将窗口切换到UserV?

任何有关更好主意的建议都非常受欢迎!

非常感谢!

1 个答案:

答案 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模式上有很多可用的阅读材料。我建议你阅读这篇文章。