使用MVVMLight在ViewModels之间传递参数

时间:2014-12-07 19:47:32

标签: c# silverlight windows-phone-8.1 mvvm-light viewmodellocator

我在使用MVVMLight框架中的Messenger类在我的ViewModel之间传递参数时遇到问题。

这是我使用的代码:

ViewModelLocator

public ViewModelLocator ()
{
    ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

    SimpleIoc.Default.Register<INavigationService, NavigationService>();

    SimpleIoc.Default.Register(() => new MainViewModel(NavigationService));
    SimpleIoc.Default.Register(() => new SecondViewModel(NavigationService));
}

public MainViewModel MainViewModel
{
    get { return SimpleIoc.Default.GetInstance<MainViewModel>(); }
}

public SecondViewModel SecondViewModel
{
    get { return SimpleIoc.Default.GetInstance<SecondViewModel>(); }
}

public INavigationService NavigationService
{
    get { return SimpleIoc.Default.GetInstance<INavigationService>(); }
}

MainViewModel

private void ShowPersonDetailsCommand(object obj)
{
    Messenger.Default.Send((Person)obj);
    _navigationService.NavigateTo(new Uri("/SecondPage.xaml", UriKind.Relative))
}

SecondViewModel

public SecondViewModel(INavigationService navigationService)
{
    _navigationService = navigationService;

    Messenger.Default.Register<Person>(
        this,
        person =>
        {
            Person = person;
        });
}

在我的MainViewModel(ShowPersonDetailsCommand)中,我导航到SecondPage并在Messenger类中将人员作为参数发送。在这一点上,这个人构造得很好,并作为信息发送。

但是在SecondViewModel构造函数中,该人为空:(

我有什么遗失的吗?

我认为我做错了什么......

供参考:

  • Windows Phone 8.1(Silverlight)

  • MVVMLight 5.0.2

  • Visual Studio 2013 Update 4

3 个答案:

答案 0 :(得分:8)

我建议在SecondViewModel注册后立即创建ViewModelLocator。您可以使用Register的重载方法来完成此操作。

SimpleIoc.Default.Register<SecondViewModel>(true);

这将确保在发送邮件之前确保Messenger注册。

答案 1 :(得分:1)

发送邮件时,尚未创建SecondViewModel;它仅在您访问SecondViewModel的{​​{1}}属性时创建。因此,您的邮件已发送,并且未被任何操作处理。然后,当创建ViewModelLocator实例时,消息已经发送...

我建议您在致电SecondViewModel后发送消息,它应该解决问题。

答案 2 :(得分:0)

您可以在NavigationServicesEx.Navigate方法调用中传递参数,而不是发送消息。

Marco Minerva的这个blog建议如何在目标页面导航到的时候挂钩到Frame_Navigating事件(它从vanilla NavigationServiceEx类中丢失)以访问参数。

创建博客中描述的INAVigable界面:

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

为NavigationServicesEx类中的Frame.Navigating事件添加处理程序(带有一些额外的管道,请参阅博客),然后在ViewModel中实现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;
}