MVVM Light,Windows Phone,View&页面之间的ViewModel导航

时间:2011-07-20 12:05:02

标签: silverlight windows-phone-7 mvvm

我有一个页面,您基本上可以选择一组选项(配置),然后转到下一页,您可以在其中执行某些操作 使用MVVM Light工具包,我有一个viewmodel绑定到第一页的视图。当用户点击按钮时,它会重定向到另一个视图,这将是第二页 即:

Page2Command = new DelegateCommand((obj) => 
    Messenger.Default.Send<Uri>(new Uri("/DoStuffView.xaml", UriKind.Relative), 
                                Common.CommonResources.GoToDoStuffRequest)) });

问题是,第二个视图的viewmodel(我看到它的方式)在构造函数中有几个参数,它们基本上是对第一页上设置的配置的依赖。

即。 :

public DoStuffViewModel(ICollection<Note> availableNotes, SoundMappers soundType)
{
}

问题出在这里..如何使用第一页上用户动态选择的数据来实例化viewmodel?。

我无法使用MVVM光提供的ViewModelLocator模式,因为这些视图模型没有任何依赖关系,它们只是它们自己(或者它们可以从数据库,文件或其他任何方式检索数据,但它们没有任何动态输入数据)。我可以通过视图的构造函数来实现它,在那里实例化viewmodel,并为视图的DataSource分配新创建的视图模型,但我认为这样做并不是很好。 建议?

3 个答案:

答案 0 :(得分:3)

我看到你使用Messenger类发送消息,因此你熟悉MVVM中的消息传递。您必须定义自己的消息类型,该类型应接受第1页的参数:

    public class Page2ViewModelCreateMessage : MessageBase
{
    public ICollection<Note> AvailableNotes{get;set;}
    public SoundMappers SoundType{get;set;}

    public Page2ViewModelCreateMessage ()
    {

    }

    public Page2ViewModelCreateMessage(ICollection<Note> availableNotes, SoundMappers soundType)
    {
        this.AvailableNotes = availableNotes;
        this.SoundType = soundType;
    }
}

您必须使用参数发送Page2ViewModelCreateMessage实例并在导航时发送:

var message = new Page2ViewModelCreateMessage(myAvailableNotes, mySoundType)
Messenger.Default.Send(message);

在Page2上,您必须注册接收类型为Page2ViewModelCreateMessage的消息:

        Messenger.Default.Register<Page2ViewModelCreateMessage>(this, OnPage2ViewModelCreateMessage);
    ..
    public void OnPage2ViewModelCreateMessage(Page2ViewModelCreateMessage message)
    {
        var page2ViewModel = new Page2ViewModel(messsage.AvailableNotes, message.SoundType);
    }   

正如您所看到的,我已将Page2ViewModel替换为DoStuffViewModel,以便更清晰。

我希望这会对你有所帮助。

注意:我不保证代码可以像写在记事本中那样工作。

答案 1 :(得分:1)

我这样做的方法是通过一个接口建立一个ViewModel都知道的中央控制器类。然后我让手机为我执行导航之前设置状态。然后,每个ViewModel都会询问此中心类以获取所需的状态。

对我来说有很多好处:

  • 它允许我拥有非静态ViewModels。
  • 我可以使用Ninject来注入控制器类的具体实现,并将其作为一个单例进行定位。
  • 最重要的是,当墓碑化时,我只需要抓取当前的ViewModel和控制器类。

我遇到了一个问题,我的ViewModel是注册的监听器,因为我是View First而不是ViewModel首先,我被迫使用静态ViewModel引用。否则,未及时创建ViewModel以接收消息。

我将控制器类与消息一起使用(它基本上是UI周围所有消息的接收者)所以将来如果我重构,我不需要改变太多,只需要消息的收件人。

想想看,控制器类也是我的导航接收器 - 因为我有一些自定义导航代码可以跳过某些页面上的分页等。

以下是我当前设置的一个示例:

public interface IController
{
    Foo SelectedFoo { get; }
}

public class ViewModel
{
    private IController _controller;

    public ViewModel(IController controller)
    {
        _controller = controller;
    }

    private void LoadData()
    {
        // Using selected foo, we load the bars.
        var bars = LoadBars(_controller.SelectedFoo);
    }
}

答案 2 :(得分:0)

您可以使用PhoneApplicationService字典保存从第一个事件导航时所需的数据,并在导航到第二个页面时解析它。您也可以在ViewModel中使用该数据。 像这样:

 PhoneApplicationService.Current.State["DatatFromFirstPage"] = data;

当导航到第二页时:

 if (PhoneApplicationService.Current.State.ContainsKey("DatatFromFirstPage"))
 {
      var dataUsedOnSeconPage= PhoneApplicationService.Current.State["DatatFromFirstPage"];
 }

您可以在整个应用中全局使用此数据