Передача параметра между ViewModels с использованием MVVMLight
У меня проблема с передачей параметров между моими ViewModels с использованием класса Messenger в MVVMLight Framework.
Это код, который я использую:
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, обновление 4
3 ответа
Я бы предложил создать SecondViewModel
сразу же, как только он зарегистрирован в ViewModelLocator
, Вы можете сделать это, используя перегруженный метод Register
,
SimpleIoc.Default.Register<SecondViewModel>(true);
Это позволит убедиться, что Messenger
регистрация происходит до отправки сообщения.
Когда вы отправили сообщение, SecondViewModel
еще не был создан; он создается только при доступе к SecondViewModel
собственность ViewModelLocator
, Итак, ваше сообщение было отправлено, и ничем не обработано. Затем, когда SecondViewModel
экземпляр создан, сообщение уже отправлено...
Я предлагаю вам отправить сообщение после звонка NavigateTo
, это должно решить проблему.
Вместо отправки сообщения вы можете передать параметр в вызове метода NavigationServicesEx.Navigate.
В этом блоге Марко Минервы рассказывается, как подключиться к событию Frame_Navigating (которое отсутствует в классе vanilla NavigationServiceEx), чтобы получить доступ к аргументу при переходе на целевую страницу.
Создайте интерфейс INavigable, описанный в блоге:
public interface INavigable
{
Task OnNavigatedToAsync(object parameter, NavigationMode mode);
void OnNavigatingFrom(NavigatingCancelEventArgs e);
void OnNavigatedFrom();
}
Добавьте обработчик для события Frame.Navigating в классе NavigationServicesEx (с некоторыми дополнительными функциями, см. Блог), затем реализуйте интерфейс INavigable в ваших моделях ViewModels.
После этого вы сможете получить доступ к параметру, который вы передали в своем вызове Navigate:
NavigationServiceEx.Navigate(typeof(DestinationPage).FullName, yourParameter);
В методе OnNavigatedToAsync, который вы реализуете в своей модели представления:
public Task OnNavigatedToAsync(object parameter, NavigationMode mode)
{
if (parameter != null)
{
YourThing thing = parameter as YourThing;
this.UseYourThing(thing);
}
return Task.CompletedTask;
}