powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / Открытие дочернего окна, передача данных между ViewModel-ями окон
8 сообщений из 8, страница 1 из 1
Открытие дочернего окна, передача данных между ViewModel-ями окон
    #38707076
monstrilla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день. Есть концептуальный вопрос по разработке приложений с использованием паттерна MVVM. А именно открытие дочернего окна из основного, например по кнопке + как правило, нужно передавать данные из ViewModel-и первого окна во ViewModel второго и обратно.

У меня есть два подхода к реализации этого сценария, но оба эти варианта кажутся мне неидеальными (а один из них вообще съедает много времени без видимой пользы). Я могу в подробностях их изложить здесь, мы побеседуем и придем к какому-то консенсусу. Просто на изложение уйдет много букв (времени) и не хотелось бы набирать все впустую, а в результате никто не ответит. В общем, если кто-то считает себя опытным применителем паттерна MVVM и, возможно, сам многократно сталкивался с такой задачей — дайте знать и я распишу все в деталях.

С уважением.
...
Рейтинг: 0 / 0
Открытие дочернего окна, передача данных между ViewModel-ями окон
    #38707225
monstrilla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вот расписал.

Есть ViewOne и соответствующая модель ViewModelOne, ViewTwo и соответствующая модель ViewModelTwo. ViewOne и ViewTwo – окна.
Типичная ситуация. Во ViewOne есть кнопка, по нажатию на которую открывается окно ViewTwo. Т.е. есть команда во ViewModelOne, назовем ее OpenViewTwoCommand, привязанная к событию Click кнопки. Команда в свою очередь вызывает метод OpenViewTwoMethod и в этом методе «открывается» окно.

Вариант первый.

В методе OpenViewTwoMethod создается экземпляр ViewModelTwo и ViewTwo. Данные из ViewModelOne передаются во ViewModelTwo через свойства. Точно так же через свойства их удобно считывать, когда окно будет закрыто.
Недостатки:
Для ViewTwo невозможно проинициализировать свойство Owner, ведь ViewModelOne ничего не знает о ViewOne. Лечится хранением в ViewModelOne указателя на ViewOne (проинициализировать можно на событие Loaded окна ViewOne). Но тут возникает вопрос о корректности такого подхода, не противоречит ли он принципам MVVM?

Вариант второй.

Где то на stackoverflow я вычитал, что кошерно когда View открывает View, а Модель создает Модель. Суть в следующем. Жмем на кнопку во ViewOne, срабатывает команда в ViewModelOne, создается ViewModelTwo, а так же сообщение специального типа, в него помещается ViewModelTwo и шлется сообщение окну ViewOne посредством Messenger.Default.Send. ViewOne регистрируется на получение сообщения и при получении оного открывает ViewTwo. Идея показалась абсолютно логичной и очень понравилась. Настолько что я стал везде применять этот подход, но, как говорится, «все было слишком хорошо, чтобы быть правдой»

Недостатки:
1) Самый очевидный – необходимость создания типов сообщений. Если на форме 10 кнопок , открывающих разные окна – 10 типов сообщений. Несложно, но время то ест.
2) Менее очевидный . Если мне нужно по закрытию ViewTwo выполнять какие-то действия с данными, которые находятся во ViewModelTwo – нужно во ViewModelOne отслеживать событие закрытия окна. Т.е. объявлять обработчик событий, возможно еще и создавать специальный тип-хелпер для аргументов события + делегат.
3) Следует из второго.
Пусть OpenViewTwoMethod – метод, в котором открывается ViewTwo.
private void OpenViewTwoMethod()
{
// обработка данных ViewModelOne, получили DataViewModelOne - не суть какие данные
// открытие окна ViewTwo
}

/// <summary>
/// Событие закрытия окна ViewTwo
/// </summary>
private void ViewTwoClosed()
{
// а вот тут мне нужно еще что-то сделать с DataViewModelOne, учитывая данные из ViewModelTwo
// получается мне нужно дополнительно хранить DataViewModelOne в ModelViewOne
}

А вы что посоветуете? :)
...
Рейтинг: 0 / 0
Открытие дочернего окна, передача данных между ViewModel-ями окон
    #38714645
iMrTidy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
monstrilla,

Здесь на мой взгляд представлен наилучший вариант решения это проблемы. А здесь похожаля логика, но максимально упрощенная.
...
Рейтинг: 0 / 0
Открытие дочернего окна, передача данных между ViewModel-ями окон
    #38720114
Супер_Пав
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
monstrilla,
в 1й вьехе добавляем команды, например:
Код: c#
1.
public ICommand SomeCommand { get; set; }


далее создаем класс для команды:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
public class SomeCommand : ICommand
    {
        #region Fields

        private readonly FirstViewModel _firstViewModel;

        #endregion

        #region Constructor

        public SomeCommand (FirstViewModel firstViewModel)
        {
            _firstViewModel = firstViewModel;
        }

        #endregion

        #region ICommand Members
        
        public bool CanExecute(object parameter)
        {
            return true;
        }
       
        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }
        
        public void Execute(object parameter)
        {
            //Тут открываем любую форму и все данные передаём в первую вьюху через локальную переменную__firstViewModel
        }

        #endregion
    }


далее в конструкторе 1й вьюхи:
Код: c#
1.
this.SomeCommand = new SomeCommand(this);
...
Рейтинг: 0 / 0
Открытие дочернего окна, передача данных между ViewModel-ями окон
    #38724786
monstrilla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
iMrTidy,

спасибо, очень интересно, разбираю.

Супер_Пав,

жесть какая-то :)
...
Рейтинг: 0 / 0
Открытие дочернего окна, передача данных между ViewModel-ями окон
    #38725873
monstrilla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Разобрал. Оно, конечно работает, но на мой взгляд излишне усложнено. Во-первых можно обойтись безо всех интерфейсов, т.к. они не используются как интерфейсы. По сути, существуют только для проформы и на них завязана логика работы ServiceLocator-а. О этом типе см ниже.

OpenFileDialogViewModel, FolderBrowserDialogViewModel - просто классы, объекты которых используются для инициализации виндовых окон, т.е. если инитить окна напрямую - можно обойтись и без них. Кстати, окошки типа MessageBox именно так и инитятся. Посему непонятно, почему автор по аналогии не запилил тип MessageBoxViewModel и интерфейс IMessageBoxViewModel.

OpenFileDialog, FolderBrowserDialog - не более чем обертки над виндовыми диалоговыми окнами. Зачем они, если можно напрямую создать экземпляры окон System.Windows.Forms.OpenFileDialog и System.Windows.Forms.FolderBrowserDialog?

Вся соль, сосредоточена в классе DialogService. Его можно просто запилить как синглтон (тогда надобность в типе ServiceLocator отпадает вообще). В общем, считаю, что можно написать в 3 раз более простой и меньший по объему код, который будет делать в точности то же самое.

Возможно, я чего то не знаю :)
...
Рейтинг: 0 / 0
Открытие дочернего окна, передача данных между ViewModel-ями окон
    #38725899
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
monstrillaВозможно, я чего то не знаю :)Меньше знаешь - крепче спишь... :-)
monstrillaРазобрал. Оно, конечно работает, но на мой взгляд излишне усложнено. Во-первых можно обойтись безо всех интерфейсов, т.к. они не используются как интерфейсы. По сути, существуют только для проформы и на них завязана логика работы ServiceLocator-а. О этом типе см ниже.Мир в наше время повёрнут на подстановке альтернативной реализации сервисов на этапе тестирования. Отсюда фанатичная тяга к интерфейсам и диконтейнерам.
monstrillaВ общем, считаю, что можно написать в 3 раз более простой и меньший по объему код, который будет делать в точности то же самое.Часто так и есть, но не всегда.
...
Рейтинг: 0 / 0
Открытие дочернего окна, передача данных между ViewModel-ями окон
    #38725926
monstrilla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Алексей К,

Да, я совершенно не использую юнит-тесты, и даже не знаю(пока) как они работают :) Тестируем работоспособность функционала методом тыка в разные места интерфейса.

Наверное, вся эта "лишняя" обвязка для юнит-тестов и нужна.
...
Рейтинг: 0 / 0
8 сообщений из 8, страница 1 из 1
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / Открытие дочернего окна, передача данных между ViewModel-ями окон
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]