豆瓣电台WP7客户端 MVVM重构记录之使用MVVM Light的Message实现导航
这几天使用MVVM重构这个应用,发现一个严重的问题,那就是导航。基于MVVM的思想,View跟ViewModel之间依靠绑定等技术通信,而且是View可以拿到ViewModel,ViewModel不可以拿到View。本来用CodeBehind的时候很容易的导航,到这里就无从下手了。当然也是有办法把View传递到ViewModel的,不过这样就破坏了MVVM的初衷了。
解决这个问题,首先需要解决怎么在ViewModel中得到NavgationServices来导航。以下是解决办法:
root = Application.Current.RootVisual as PhoneApplicationFrame;
拿到这个root之后就可以导航了。
root.Navigate(pageUri);
不过这样直接在ViewModel里导航总感觉比较唐突,而且有个重要的问题,那就是使用CodeBehind时,可以依靠重写OnNavigatedTo等这种方法来处理的逻辑在ViewModel里如何来处理。当了解了MVVM Light的Message机制之后,我想到了一套解决方案。
MVVM Light的Message机制可以Send一个消息,它会被广播出去,然后被register的对象接收,然后调用指定的方法。
思路:
当一个VM需要导航的时候,Send一个Message把导航的URL传递出去,这个消息被一个NavgationController截获,执行导航操作,导航完成之后NavgationController会Send一个Message,通知导航到的View对应的ViewModel执行Navigated方法。
NavigationHelper:
using System;
using System.Collections.Generic;
using System.Windows;
using Microsoft.Phone.Controls;
using GalaSoft.MvvmLight.Messaging;
namespace MvvmLightNavgation
{
public class NavigationHelper
{
private static PhoneApplicationFrame root;
public static PhoneApplicationFrame GetPhoneFrameRoot()
{
if (root == null)
{
root = Application.Current.RootVisual as PhoneApplicationFrame;
if (root == null)
{
throw new Exception("获取 ApplicationRootVisual 失败!");
}
}
return root;
}
/// <summary>
/// 根据url字符串导航
/// </summary>
/// <param name="url"></param>
public static void NavigationTo(string url)
{
if (root==null)
GetPhoneFrameRoot();
if(root !=null)
{
var pageUri = new Uri(url, UriKind.Relative);
root.Navigate(pageUri);
}
}
/// <summary>
/// 根据Uri导航
/// </summary>
/// <param name="pageUri"></param>
public static void NavigationTo(Uri pageUri)
{
if (root == null)
GetPhoneFrameRoot();
if (root != null)
{
root.Navigate(pageUri);
}
}
public static Uri CreateUri(string url)
{
return new Uri(url, UriKind.RelativeOrAbsolute);
}
/// <summary>
/// 发送导航Msg
/// </summary>
/// <param name="pageUri"></param>
public static void NavigationMsgSend(Uri pageUri)
{
Messenger.Default.Send(pageUri, MsgToken.Navigation);
}
/// <summary>
/// 发送导航Msg
/// </summary>
/// <param name="pageUrl"></param>
public static void NavigationMsgSend(string pageUrl)
{
Messenger.Default.Send(CreateUri(pageUrl), MsgToken.Navigation);
}
/// <summary>
/// 注册导航完成MSG
/// </summary>
public static void NavigatedMsgReg(object recipient)
{
INavigation navigation = recipient as INavigation;
if (navigation!=null)
{
Messenger.Default.Register<Uri>(recipient, navigation.GetViewUrl(), navigation.Navigated);
}
}
}
}
这个类提供了一堆静态方法来实现页面之间的导航。其中最重要的方法是:
/// <summary>
/// 发送导航Msg
/// </summary>
/// <param name="pageUrl"></param>
public static void NavigationMsgSend(string pageUrl)
{
&n
补充:移动开发 , Windows Phone ,