2

我正在开发一个 Windows Phone 7 应用程序。现在我需要在用户点击将用户带到另一个视图的指定按钮后切换视图。

理论上,MVVM 中的哪个组件应该负责导航,即切换视图?代码片段可以很好地展示。

我尝试在 View 中插入切换代码,它工作正常,但是我遇到了调用异步 Web 服务并希望仅在操作完成后将用户导航到新视图的情况,导航代码应该在里面事件处理程序。

谢谢你。

P/S:我的项目的截止日期快到了,我没有时间使用 MVVM 工具重建我的项目,例如 MVVM Light、Caliburn Micro 等。

4

3 回答 3

2

我在所有 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 状态)以及如何到达那里。

于 2013-06-01T14:58:51.113 回答
0

我将导航放在 MVVM 之外的一个类中,该类负责显示/隐藏视图。

ViewModel 使用带有弱事件的消息代理将消息发布到此类。

这种设置给了我最大的自由,并且没有将任何责任放在不属于那里的 MVVM 类中。

于 2013-06-01T16:58:52.103 回答
0

该视图应具有有限数量的可能目的地。如果您必须在每个页面上都有一个顶级导航,那应该是您布局的一部分,或者您可以将它们放在子视图中。

于 2013-06-01T16:49:12.650 回答