Страницы

Поиск по вопросам

среда, 25 декабря 2019 г.

Несколько вопросов по паттерну MVVM

#c_sharp #wpf #xaml #mvvm

Навели меня на мысль, что весь мой код является "говнокодом", потому что мои WPF
приложения не соответствуют паттерну MVVM. Я начал про это читать, но в интернетах
информация изложена слишком сложно для моего понимания. Поэтому я задам несколько вопросов,
которые откроют мне глаза (я надеюсь)


Допустим, я создаю UserControl. При этом UserControl.xaml является View, а UserControl.xaml.cs
- ViewModel? Или ViewModel - это еще один дополнительный класс, например UserControlViewModel?
Я пока склоняюсь ко второму варианту, но не уверен.
Если в прошлом вопросе правильным является второй вариант, то где мне создавать DependenceProperties?
В UserControl.xaml.cs или в UserControlViewModel? Я пока склоняюсь к первому варианту.
Если UserControl содержит команды, которые надо добавить к главному меню окна, в
котором его расположили, то как это лучше осуществить, не отклоняясь от MVVM? Причем
сделать это надо с иерархией. Первое, что приходит на ум - создать в ресурсах UserControl
новое Menu. но при слиянии иерархию надо сохранить. То есть если в главном окне уже
есть меню "Файл", и оно используется в контроле, то элементы контрола должны добавиться
к элементам этого меню в окне без создания еще одного меню "Файл".


UPD:

И еще, что такое Model?

UPD2:

К примеру, мне надо вывести в ListBox коллекцию экземпляров класса MyClass

public class MyClass
{
    public string Prop1 { get; set; }
    public string Prop2 { get; set; }
}


в виде Prop1(Prop2)

Как мне поступить, чтобы соответствовать MVVM?

Раньше я делал так 


    
        
            
    



Получается, что это неверный подход? Или что?

UPD3:

Еще вопрос. Вью и вью-модель связываются, например, через DataСontext вьюшки (других
способов я не знаю). В этом случае вью-модель не имеет параметров у конструктора. А
как тогда связать вью-модель и модель?

UPD4:

У меня еще вопрос. Вот есть у меня модель, вью-модель и вью. Вью-модель подписана
на изменение свойств модели (хоть через PropertyChanged, хоть через отдельные события).
Тогда получится следующее. Во вьюшке чего то меняется (пользователь изменил текст в
текстовом поле).
Через биндинг это передается в сеттер вью-модели, в которой написано следующее _model.Property
= value. Но я ведь подписан на изменение свойств модели. Получается, что модель после
изменения Property сообщит вью-модели, что ее свойство изменилось, вью-модель вызовет
PropertyChanged и во вьюшке применится это значение в текстовом поле. По сути ничего
страшного не произойдет, кроме того, что программа выполнит ЛИШНИЕ ДЕЙСТВИЯ
    


Ответы

Ответ 1



Модель представления - это еще один дополнительный класс. Представление не обязательно должно быть UserControl'ом. Это может быть, например, словарь ресурсов с шаблоном данных для модели представления. Тогда ни о каком code-behind речи быть не может. Свойства зависимости нужно создавать в code-behind контрола (т.е. UserControl.xaml.cs). Это часть представления и модели представления о них знать не нужно. UserControl не должен содержать команды. Он должен привязываться к командам модели представления. Если нужна иерархия, то делайте иерархию команд в модели представления плагина (предполагаю, что вы делаете что-то плагинообразное) и сливайте их с командами модели представления главного окна. Еще я бы посоветовал избавиться от иерархии команд и подумать над тем, как их можно представить плоским списком. UPD Я согласен с Discord, потому и посоветовал делать плоский список. Это может быть набор команд в модели представления: OpenFileCommand, SaveFileCommand и т.д. А в представлении это уже будет иерархией: меню файл содержит пункты "открыть" и "сохранить". Если у вас ситуация, когда пол проекта написана на WinForms, а половина на WPF, то, возможно, ваше решение вполне подходит. Просто после переноса проекта нужно не забыть переделать эту часть. Когда мы перетаскивали проект в WinForms на WPF, то сначала изменили главное окно приложения: оно научилось работать с плагинами и формировать меню из них. Все компоненты на WinForms мы обернули в WindowsFormsHost А потом уже переделывали плагины на WPF по одному. Модель - это то, для чего вы делали модель представления (например, какой-нибудь объект из БД). Примерно так: модель - то, что нужно показать пользователю; представление - то, что видит пользователь; модель представления - связующее звено с командами и доп. свойствами, необходимыми для корректной работы представления. UPD2 С ходу довольно сложно придумать нормально решение, а на практике с именно такой задачей я не сталкивался. Например, вы можете сделать пачку интерфейсов типа: // команды, расширяющие пункт меню "Файл". interface IFileCommandsProvider { List Commands { get; } } А потом: если вкладка реализует этот интерфейс, то добавить перечень команд в меню. Либо подумать над вариантом с чем-то вроде RegionManager'а из Prism. UPD4 В описанном вами случае эти действия выполнять не надо. Если по какой-то причине (например, чтобы повесить атрибуты валидации), вы хотите спрятать свойство модели за свойством модели представления, то в модели представления имеет смысл написать следующий код: public int Property { get { return _model.Property; } set { if (_model.Property != value) { _model.Property = value; OnPropertyChanged(); } } } Тогда всю работу со свойством Property внутри модели представления нужно будет осуществлять через свойство модели представления. Т.е. кода _model.Property = value больше нигде не должно встречаться. Тогда вам не нужно будет подписываться на Model.PropertyChanged("Property").

Комментариев нет:

Отправить комментарий