我在所有 ViewModel 共享的基类中放置了一个 Navigate 方法:
protected void Navigate(string address)
{
if (string.IsNullOrEmpty(address))
return;
Uri uri = new Uri(address, UriKind.Relative);
Debug.Assert(App.Current.RootVisual is PhoneApplicationFrame);
BeginInvoke(() =>
((PhoneApplicationFrame)App.Current.RootVisual).Navigate(uri));
}
protected void Navigate(string page, AppViewModel vm)
{
// this little bit adds the viewmodel to a static dictionary
// and then a reference to the key to the new page so that pages can
// be bound to arbitrary viewmodels based on runtime logic
string key = vm.GetHashCode().ToString();
ViewModelLocator.ViewModels[key] = vm;
Navigate(string.Format("{0}?vm={1}", page, key));
}
protected void GoBack()
{
var frame = (PhoneApplicationFrame)App.Current.RootVisual;
if (frame.CanGoBack)
frame.GoBack();
}
因此,如果您要求的是 ViewModel 基类,则会执行导航。然后通常一些派生的 ViewModel 类控制导航的目标,以响应绑定到视图中的按钮或超链接的 ICommand 的执行。
protected SelectableItemViewModel(T item)
{
Item = item;
SelectItemCommand = new RelayCommand(SelectItem);
}
public T Item { get; private set; }
public RelayCommand SelectItemCommand { get; private set; }
protected override void SelectItem()
{
base.SelectItem();
Navigate(Item.DetailPageName, Item);
}
所以 View 只知道何时需要导航操作,而 ViewModel 知道去哪里(基于 ViewModel 和 Model 状态)以及如何到达那里。