如果您已经在使用 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()
{
//Logic for determining next view, then ...
Messenger.Default.Send(new NavigationMessage("ViewToNavigate"));
}
最后,视图基类如下所示:
public class BasePage : PhoneApplicationPage
{
public BasePage()
{
Messenger.Default.Register<NavigationMessage>(this, NavigateToPage);
}
protected void NavigateToPage(NavigationMessage message)
{
//GetQueryString isn't shown, but is simply a helper method for formatting the query string from the dictionary
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));
}
}
这是假设所有视图都位于应用程序根目录中的“视图”文件夹中的约定。这适用于我们的应用程序,但当然可以扩展它以支持您如何组织视图的不同场景。