すべての 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 クラスが、View 内のボタンまたはハイパーリンクにバインドされた 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 の状態に基づいて) 移動先とそこに到達する方法を認識します。