【问题标题】:MVVM-Light pass data to new ViewModelMVVM-Light 将数据传递给新的 ViewModel
【发布时间】:2015-01-20 09:45:32
【问题描述】:

只是摆弄一些 WP8.1 开发 + MVVM-Light 工具包,并且在试图弄清楚如何实现某些目标时遇到了麻烦..

基本上:

  • 我有一个View(我们称之为View1),它有一个控件(在本例中为LongListSelector),它数据绑定到一个项目集合(我们称之为DataItem)(由Service 来自 ViewModel)

我想要这样:

  • 当用户点击此控件中的特定项目时,它将被点击的项目(或该项目的属性)传递给新的View(称为View2),这将创建一个新的ViewModel用于View2 或重新使用现有的(取决于SimpleIoC 中实例的Key,由DataItem 中的某些属性确定)。
  • 这个新的ViewModel 然后使用DataItem 在其构造函数中的传递属性从不同的Service 获取数据

那么我该如何实现呢?我正在考虑在控件的SelectionChanged 事件上创建/注册新的ViewModel,并将其传递给ServiceProperty,如下所示:

    private void LongListSelector_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        DataItem item = e.AddedItems[0] as DataItem;

        SimpleIoc.Default.Register(() => new ViewModel2(new Model2Service(), item.Name));

        NavigationService.Navigate(new Uri("/View2.xaml", UriKind.Relative));
    }

这对 first DataItem 的点击效果很好,但在第二个被点击时效果不佳。 注意:我无法在ViewModelLocator 中注册ViewModel2,因为我无法将DataItem 属性传递给ViewModel2 的构造函数,这就是我尝试注册它的原因别处。

不确定这是否符合 MVVM 架构,我想不是 this answer 声明我不应该在我的 View 中处理这个问题。

回顾一下,我希望用户能够点击LongListSelector 中的项目,然后将用户导航到新的View,该View 绑定到新的(或现有的)ViewModel到所选项目的属性。我怎样才能做到这一点?

任何帮助将不胜感激。

【问题讨论】:

    标签: c# windows-phone-8 mvvm windows-phone-8.1 mvvm-light


    【解决方案1】:

    您是否尝试过在 MVVMLight 中使用 Messenger?尝试在ViewModelLocator 中创建ViewModel2 的实例,其中键是某个默认值。在 ViewModel 的构造函数中,注册以接收 string 属性(假设 item.Namestring),如下所示:

    MessengerInstance.Register<string>(this,name=>{NameProperty=name;});
    

    然后在LongListSelector_SelectionChanged,像这样发送item.Name

    Messenger.Default.Send<string>(item.Name);
    

    然后导航到页面。


    标记为解决方案,但下面的整个评论线程揭示了更多细节

    【讨论】:

    • 感谢您的回复。此解决方案有效,但理想情况下,我希望为 each 选择不同的 DataItem 单独的 ViewModels 实例,这将允许我:在更新页面导航之前显示以前加载的数据。想法?
    • 好的。在事件处理程序中,不是将DataItem.name 传递给视图模型的构造函数,您是否尝试过使用Register 方法的重载和key 参数(使用item.name)?然后在Navigate 方法中,将key 作为参数传递。在View2OnNavigatedTo方法中,获取参数并使用ServiceLocator.Current.GetInstance(key)获取所需的视图模型并在视图上设置DataContext
    • 谢谢,ViewModel2all 实例接收消息并将NameProperty 设置为消息时遇到问题,因此我修改了解决方案:当用户点击@ 987654345@, NavigationService.Navigate 被调用,将查询字符串&amp;name=.. 传递给View2,并在OnNavigatedTo 中检索此查询字符串并且: 1. GetInstance(name) 返回带有key=name 的旧实例或新实例,2 . 刷新数据(在成功时设置NameProperty,3. 设置DataContext!就像一个魅力。我唯一的抱怨是:像这样设置DataContext 被认为是糟糕的设计 MVVM?
    • 这本身并不是一个糟糕的设计。在 XAML 中设置 DataContext 被认为是最佳实践,因为它允许您查看在设计时发生的绑定。但是在很多情况下(例如这种情况),您需要在代码隐藏中进行设置。唯一的缺点是您在设计时看不到绑定发生。但是可以通过创建设计时 DataContext 来解决此问题。
    • 我明白了,感谢您的澄清。我的设计时 DataContext 已经启动并运行了:),只需要为我的问题找出一个更“架构一致”的设计——你已经完成了!感谢您的帮助好友。
    【解决方案2】:

    如果您使用 UWP 与 Template Studio 10 和 MVVM Light 并希望:

    • 访问在 NavigationServicesEx.Navigate 方法中传递的参数

    • 在导航到页面时调用 ViewModel 中的方法。

    Marco Minerva 的 blog 是我能找到的唯一指南,它与 UWP、Templates Studio 10 和 MVVM Light 5.0 保持同步(再次感谢 Marco!)

    tl;dr它的工作原理是连接到普通 NavigationServiceEx 类中缺少的 Frame_Navigating 事件。

    创建博客中描述的 INavigable 接口:

    public interface INavigable
    {
        Task OnNavigatedToAsync(object parameter, NavigationMode mode);
        void OnNavigatingFrom(NavigatingCancelEventArgs e);
        void OnNavigatedFrom();
    }
    

    在 NavigationServicesEx 类中为 Frame.Navigating 事件添加一个处理程序(带有一些额外的管道,请参阅博客),然后在您的 ViewModels 中实现 INavigable 接口。

    然后您将能够访问您在 Navigate 调用中传递的参数:

    NavigationServiceEx.Navigate(typeof(DestinationPage).FullName, yourParameter);
    

    在您在 ViewModel 中实现的 OnNavigatedToAsync 方法中:

    public Task OnNavigatedToAsync(object parameter, NavigationMode mode)
    {
        if (parameter != null)
        {
            YourThing thing = parameter as YourThing;
            this.UseYourThing(thing);
        }
        return Task.CompletedTask;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-07
      • 1970-01-01
      • 1970-01-01
      • 2014-10-01
      相关资源
      最近更新 更多