如果您已经在使用MVVM Light,其中一种选择是利用它包含的消息总线。所以,您可以像您已经做过的那样,在视图模型上将按钮绑定到RelayCommand。在RelayCommand的处理程序中,您可以决定要导航到哪个视图。这将保留所有逻辑在视图模型中。
一旦您的命令处理程序决定要导航到哪个视图,它就可以在消息总线上发布一条消息。您的视图将会监听该消息,然后使用NavigationService来实际执行导航。因此,它除了等待被告知何时导航到某个位置并导航到指示的位置外,不会做任何其他事情。
我通过定义一个NavigationMessage类来实现这一点,我的视图模型可以发布该类,并且我的视图基类继承了包含侦听器的内容。NavigationMessage的样式如下:
public class NavigationMessage : NotificationMessage
{
public string PageName
{
get { return base.Notification; }
}
public Dictionary<string, string> QueryStringParams { get; private set; }
public NavigationMessage(string pageName) : base(pageName) { }
public NavigationMessage(string pageName, Dictionary<string, string> queryStringParams) : this(pageName)
{
QueryStringParams = queryStringParams;
}
}
这样可以简单地传递页面名称,或者还可以选择包括任何必要的查询字符串参数。一个RelayCommand处理程序会像这样发布这条消息:
private void RelayCommandHandler()
{
Messenger.Default.Send(new NavigationMessage("ViewToNavigate"));
}
最后,视图基类如下所示:
public class BasePage : PhoneApplicationPage
{
public BasePage()
{
Messenger.Default.Register<NavigationMessage>(this, NavigateToPage);
}
protected void NavigateToPage(NavigationMessage message)
{
string queryStringParams = message.QueryStringParams == null ? "" : GetQueryString(message);
string uri = string.Format("/Views/{0}.xaml{1}", message.PageName, queryStringParams);
NavigationService.Navigate(new Uri(uri, UriKind.Relative));
}
}
假设所有视图都在应用程序根目录下的“Views”文件夹中,这适用于我们的应用程序,但当然可以扩展以支持不同的场景来组织您的视图。