Обновление viewmodel из другой viewmodel
У меня есть две ViewModels один прикреплен к главному окну, а другой прикреплен к дочернему окну, которое открывается, нажав на кнопку в главном окне. Дочернее окно содержит список элементов, и я хочу выбрать элемент и отобразить его в главном окне, обновив viewmodel главного окна. Как лучше всего этого добиться? Спасибо!
5 ответов
существует множество способов сделать это.
передайте ссылку на модель main/parent view в дочерний элемент и попросите ребенка вызвать модель main view.
пусть дочерняя модель представления запускает событие, на которое подписывается родитель.
используйте посланника / посредника для связи между ними. Родитель подписывается, ребенок отправляет сообщение. Это обеспечивает свободный связь.
настройка модели основного вида в качестве глобальной службы. Зарегистрируйте его как-нибудь. Попросите ребенка посмотреть службу (требование глобальных служб-довольно распространенная проблема), а затем вызвать что-то на глобальном/общем интерфейсе.
по моему опыту, самым простым методом будет #2. Определите событие в дочерней модели представления. Родителю придется искать ребенка (я не знаю, содержит ли он его или как ваши модели представления построено) и подписаться на мероприятие.
стандартным способом связи между ViewModels является использование обмена сообщениями. Одной из хороших реализаций этого является MVVM Light Toolkit
вот некоторый (случайный) код, использующий мессенджер по умолчанию:
//Registering:
Messenger.Default.Register<IEnumerable<BookViewModel>>(this, true, fillSourceWith);
Messenger.Default.Register<DisplayModeEnum>(this, ChangeMainTemplates);
//with a specific "token"
Messenger.Default.Register<object>(this, MessageTokens.ClearList, o => BookSource.Clear());
//Sending
Messenger.Default.Send<List<BookViewModel>>(newBooks);
Messenger.Default.Send<DisplayModeEnum>(DisplayModeEnum.MediumLayout);
Messenger.Default.Send<object>(null, MessageTokens.ClearList);
лучший способ сделать это-иметь какую-то ссылку от ребенка к родителю и обновлять этого родителя при закрытии ребенка.
или вы можете иметь какое-то событие на child и позволить родителю слушать это событие. Затем вы поднимаете это событие, когда ребенок закрывается.
Messaging используется, когда обе ViewModels логически не связаны.
[rant] люди даже не знают основных принципов ООП или что?? [/rant]
у меня была такая же проблема за несколько дней до этого; -)
наконец, я использовал посредника для связи обеих моделей представления. На самом деле я использовал мессенджер от MVVM Light.
public void Search(object parameter)
{
ChildWindow window = new ChildWindow();
SearchWindow pageSearch = new SearchWindow();
window.Content = pageSearch;
window.Show();
Messenger.Default.Register<Messages.CloseWindowMessage>(this, action => this.closeWindow(action));
}
после этого я определил сообщение со всем, что мне нужно было знать из главного окна:
public class CloseWindowMessage : MessageBase
{
public bool Result { get; set; }
public Model.Selected Selected { get; set; }
}
наконец, сообщение обратно из дочернего окна вам нужно только зарегистрировать сообщение с результатом и объектом, который вы хотите получить обратно.
вы должны зарегистрироваться с код-позади вашего вида, чтобы закрыть окно.