Навели меня на мысль, что весь мой код является "говнокодом", потому что мои 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 и во вьюшке применится это значение в текстовом поле. По сути ничего страшного не произойдет, кроме того, что программа выполнит ЛИШНИЕ ДЕЙСТВИЯ
Ответ
Модель представления - это еще один дополнительный класс. Представление не обязательно должно быть UserControl'ом. Это может быть, например, словарь ресурсов с шаблоном данных для модели представления. Тогда ни о каком code-behind речи быть не может.
Свойства зависимости нужно создавать в code-behind контрола (т.е. UserControl.xaml.cs). Это часть представления и модели представления о них знать не нужно.
UserControl не должен содержать команды. Он должен привязываться к командам модели представления. Если нужна иерархия, то делайте иерархию команд в модели представления плагина (предполагаю, что вы делаете что-то плагинообразное) и сливайте их с командами модели представления главного окна. Еще я бы посоветовал избавиться от иерархии команд и подумать над тем, как их можно представить плоским списком.
UPD
Я согласен с Discord, потому и посоветовал делать плоский список. Это может быть набор команд в модели представления: OpenFileCommand, SaveFileCommand и т.д. А в представлении это уже будет иерархией: меню файл содержит пункты "открыть" и "сохранить".
Если у вас ситуация, когда пол проекта написана на WinForms, а половина на WPF, то, возможно, ваше решение вполне подходит. Просто после переноса проекта нужно не забыть переделать эту часть.
Когда мы перетаскивали проект в WinForms на WPF, то сначала изменили главное окно приложения: оно научилось работать с плагинами и формировать меню из них. Все компоненты на WinForms мы обернули в WindowsFormsHost А потом уже переделывали плагины на WPF по одному.
Модель - это то, для чего вы делали модель представления (например, какой-нибудь объект из БД). Примерно так: модель - то, что нужно показать пользователю; представление - то, что видит пользователь; модель представления - связующее звено с командами и доп. свойствами, необходимыми для корректной работы представления.
UPD2
С ходу довольно сложно придумать нормально решение, а на практике с именно такой задачей я не сталкивался. Например, вы можете сделать пачку интерфейсов типа:
// команды, расширяющие пункт меню "Файл".
interface IFileCommandsProvider
{
List
А потом: если вкладка реализует этот интерфейс, то добавить перечень команд в меню.
Либо подумать над вариантом с чем-то вроде 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").
Комментариев нет:
Отправить комментарий