|
Зависимости в MVVM в WPF
|
|||
---|---|---|---|
#18+
Итак, мы имеем для каждого представления: - собственно представление (XAML) - CodeBehind-модуль для XAML - модель представления (ViewModel) - уровень бизнес-логики (модель или контроллер, который управляет организацией представлений и т.п.) Как правильно простроить зависимости, чтобы не получить в будущем спагетти? Изначально одна зависимость уже есть CodeBehind зависит от XAML. Кто должен зависеть от VM, от кого она должна зависеть и где вообще ее место в жизненном цикле? Экземпляр VM должен создавать XAML или CodeBehind или же она должна формироваться в бизнес-логике и передаваться как параметр при создании экземпляра представления? Как с представлением взаимодействует бизнес-логика - через VM или через CodeBehind (опять же, учитывая то, что не все события, возникающие в CodeBehind, можно через ICommand ловить в VM) ... |
|||
:
Нравится:
Не нравится:
|
|||
11.10.2015, 20:19 |
|
Зависимости в MVVM в WPF
|
|||
---|---|---|---|
#18+
когда надо быстро, я в app.xaml добавляю ресурс: <vm:MainModel x:Key=MainMOdel/> и в форме DataContext={StaticResource MainModel} если надо сложнее логику, то в App.xaml можно указать процедуру загрузки и в ней создать\загрузить VM, создать V и связать. CodeBehind я лично не отделаю от View, но смысл в том, что CB не должен зависеть от VM, то есть взаимодействие только с объектами визуального дерева и не более. Возникает еще 1 момент, это окна, как открыть новое окно из VM? =) ... |
|||
:
Нравится:
Не нравится:
|
|||
11.10.2015, 21:44 |
|
Зависимости в MVVM в WPF
|
|||
---|---|---|---|
#18+
Roman Mejtesсоздать\загрузить VM, создать V и связать.то есть уровень бизнес-логики зависит и от V и от VM? А связываешь ты как. Бизнес модель привязывает MyView.DataContext=MyVM? А с чем взаимодействует бизнес-логика? Откуда забирает и куда докидывает данные, откуда получает события? Как поступать, если нужно, чтобы события взаимодействовали с ViewModel, если сам CodeBehind не зависит от VM? Транслировать через View, налепливая какие-то дополнительные ICommand? ... |
|||
:
Нравится:
Не нравится:
|
|||
11.10.2015, 22:12 |
|
Зависимости в MVVM в WPF
|
|||
---|---|---|---|
#18+
Shocker.ProRoman Mejtesсоздать\загрузить VM, создать V и связать.то есть уровень бизнес-логики зависит и от V и от VM? А связываешь ты как. Бизнес модель привязывает MyView.DataContext=MyVM? А с чем взаимодействует бизнес-логика? Откуда забирает и куда докидывает данные, откуда получает события? Как поступать, если нужно, чтобы события взаимодействовали с ViewModel, если сам CodeBehind не зависит от VM? Транслировать через View, налепливая какие-то дополнительные ICommand? Передавать события в MVVM невозможно, но совершенно спокойно можно передать делегат или предикат как свойство, через связывание. Я использую RoutedCommand и ICommand в паре. Для этого я сделал класс слушатель, он следит за автоматизируемым событием CommandExecute и CommandCanExecute и когда оно "всплывает" (так как оно бабл), вызывается связанная с этим маршрутизируемой командой, команда из модели представления (ICommand) . Всё взаимодействие из направлении из View в ViewModel идет через команды, особенно RoutedCommand вывозят в ContentPresenter'ах, списках и прочих контейрерах + кнопки + элементы меню + Application.commands. Обычно весь View я делаю в DataTemplate'ах, а ContentControl'ы (такие как формы и userControl'ы) использую очень редко, проще сделать шаблон и отобразить его в Presenter'е для любой модели. По этому CodeBehind у меня весь находится не в прикрепленных к XAMLу файлах с кодом, а отдельно в хелперах, либо я создаю нужный мне контрол с нужным поведением на базе существующих или скомпонованный из существующих примитивов. То есть, в XAML файлах кода в 99% случаев нет вообще, если он нужен он привязывается в дереве там, где необходим через Interactive или AttachedProperty. Грубо говоря, если мне нужно добавить логику Drag&Drop для панели, я создаю класс DragDropHelper, в нем прикрепляемое свойсто IsDragDropEnabled и когда его значение меняется на тру, для контрола к котому применяется значение прикрепляются все нужные мне обработчики событий. Получается, что вся логика отвечающая за Drag & Drop у меня в отдельном классе. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.10.2015, 22:47 |
|
Зависимости в MVVM в WPF
|
|||
---|---|---|---|
#18+
Roman MejtesВсё взаимодействие из направлении из View в ViewModel идет через командыНо ведь не все события спроецированы на команды, тут приходится поучаствовать CodeBehind-у. Как ты отправляешь эти события обратно в представление, чтобы они приобрели интерфейс ICommand? ... |
|||
:
Нравится:
Не нравится:
|
|||
11.10.2015, 23:07 |
|
Зависимости в MVVM в WPF
|
|||
---|---|---|---|
#18+
Shocker.ProИзначально одна зависимость уже есть CodeBehind зависит от XAML.Только если XAML содержит именованные элементы. ... |
|||
:
Нравится:
Не нравится:
|
|||
12.10.2015, 10:20 |
|
Зависимости в MVVM в WPF
|
|||
---|---|---|---|
#18+
Алексей КShocker.ProИзначально одна зависимость уже есть CodeBehind зависит от XAML.Только если XAML содержит именованные элементы. а что это дает для VM? =) VM ни чего не знает об объектах View их именнованности и в VM не должно быть не 1 ссылки на объекты View модели 2_Shocker.Pro : я тебе накидаю пример проекта и кину сюда чуток по позже, сегодня или завтра. Сегодня я что то приболел слегка, там будет как раз пример, как перехватить событие во View и вызвать соответствующую команду в ViewModel через команды, в CodeBehind или прямо из XAML. ... |
|||
:
Нравится:
Не нравится:
|
|||
12.10.2015, 14:27 |
|
Зависимости в MVVM в WPF
|
|||
---|---|---|---|
#18+
да, я ступил, для отлова событий ведь необязательно именовать объекты, так что таки-да, нет зависимости. Но, с другой стороны CB, конечно, самостоятельным объектом не является. Roman Mejtes, спасибо, это будет полезно. В любом случае, вопрос был и более общий о проектах с длинной перспективой развития - как правильно организовать зависимости|? чтобы в будущем не поиметь проблем. То есть, как я понял - это нормальная практика - делать зависимость бизнес-логики от VM. ... |
|||
:
Нравится:
Не нравится:
|
|||
12.10.2015, 15:21 |
|
Зависимости в MVVM в WPF
|
|||
---|---|---|---|
#18+
Roman MejtesАлексей Кпропущено... Только если XAML содержит именованные элементы. а что это дает для VM? =) VM ни чего не знает об объектах View их именнованности и в VM не должно быть не 1 ссылки на объекты View моделиНу если XAML не содержит именованных элементов, то code-behind не может иметь ссылок на них - в этом случае code-behind классическая ViewModel. зы: Экзотические случаи не рассматриваем. ... |
|||
:
Нравится:
Не нравится:
|
|||
12.10.2015, 17:05 |
|
Зависимости в MVVM в WPF
|
|||
---|---|---|---|
#18+
Shocker.Proда, я ступил, для отлова событий ведь необязательно именовать объекты, так что таки-да, нет зависимости. Но, с другой стороны CB, конечно, самостоятельным объектом не является .Это можно считать не только недостатком, но и преимуществом, в зависимости от ситуации. ... |
|||
:
Нравится:
Не нравится:
|
|||
12.10.2015, 17:17 |
|
Зависимости в MVVM в WPF
|
|||
---|---|---|---|
#18+
Shocker.ProВ любом случае, вопрос был и более общий о проектах с длинной перспективой развития - как правильно организовать зависимости|? чтобы в будущем не поиметь проблем.Всё как всегда - сразу продумать способ разделения на функциональные модули (например, множество банальных UserControl). Модули делать простыми, усложнять их по мере необходимости: например, если всё умещается в code-behind, то зачем выдумывать что-то ещё. ... |
|||
:
Нравится:
Не нравится:
|
|||
12.10.2015, 17:30 |
|
Зависимости в MVVM в WPF
|
|||
---|---|---|---|
#18+
Алексей Кв этом случае code-behind классическая ViewModel.Ну тогда вопрос - стремиться ли выделить VM как отдельный класс, или наоборот - стремиться уминать все в CB? ... |
|||
:
Нравится:
Не нравится:
|
|||
12.10.2015, 18:45 |
|
Зависимости в MVVM в WPF
|
|||
---|---|---|---|
#18+
Алексей Кнапример, множество банальных UserControlну вопрос-то при этом не отпадает - UC сам имеет свою VM и меняется только масштаб вопроса ) ... |
|||
:
Нравится:
Не нравится:
|
|||
12.10.2015, 18:46 |
|
Зависимости в MVVM в WPF
|
|||
---|---|---|---|
#18+
Алексей КRoman Mejtesпропущено... а что это дает для VM? =) VM ни чего не знает об объектах View их именнованности и в VM не должно быть не 1 ссылки на объекты View моделиНу если XAML не содержит именованных элементов, то code-behind не может иметь ссылок на них - в этом случае code-behind классическая ViewModel. зы: Экзотические случаи не рассматриваем. нам не надо знать имя элемента, чтоб обработать его события через Interactive.Behavior или AttachedProperty, нам не надо знать имена чтоб получить RoutedEvent или RoutedCommand. Единственное, что в XAML надо использовать имена, это связывание между элементами, анимация, триггеры, части шаблона (PartTemplate атрибут) ... |
|||
:
Нравится:
Не нравится:
|
|||
13.10.2015, 00:25 |
|
Зависимости в MVVM в WPF
|
|||
---|---|---|---|
#18+
Shocker.ProАлексей Кв этом случае code-behind классическая ViewModel.Ну тогда вопрос - стремиться ли выделить VM как отдельный класс, или наоборот - стремиться уминать все в CB?Ну я для себя решил, что по дефолту всё делается в CB, выносится в отдельный класс по необходимости: например, если вдруг потребуется наследование VM - CB этого к сожалению не умеет. Shocker.ProАлексей Кнапример, множество банальных UserControlну вопрос-то при этом не отпадает - UC сам имеет свою VM и меняется только масштаб вопроса )Внутри каждого UC вопрос может решаться по разному, в зависимости от масштабов и особенностей каждого отдельного подвопроса. :-) С другой стороны, здесь многое решают личные предпочтения. У меня в последнее время приоритеты в сторону простоты и минимального объёма кода. Если на каждый чих делать присоединяемые свойства, как тому учат современные практики - это никак не попадает под мои критерии абсолютной правильности. :-) ... |
|||
:
Нравится:
Не нравится:
|
|||
13.10.2015, 05:13 |
|
Зависимости в MVVM в WPF
|
|||
---|---|---|---|
#18+
Roman MejtesАлексей Кпропущено... Ну если XAML не содержит именованных элементов, то code-behind не может иметь ссылок на них - в этом случае code-behind классическая ViewModel. зы: Экзотические случаи не рассматриваем. нам не надо знать имя элемента, чтоб обработать его события через Interactive.Behavior или AttachedProperty, нам не надо знать имена чтоб получить RoutedEvent или RoutedCommand. Единственное, что в XAML надо использовать имена, это связывание между элементами, анимация, триггеры, части шаблона (PartTemplate атрибут)Я в курсе. :-) ... |
|||
:
Нравится:
Не нравится:
|
|||
13.10.2015, 05:14 |
|
Зависимости в MVVM в WPF
|
|||
---|---|---|---|
#18+
Алексей КShocker.Proпропущено... Ну тогда вопрос - стремиться ли выделить VM как отдельный класс, или наоборот - стремиться уминать все в CB?Ну я для себя решил, что по дефолту всё делается в CB, выносится в отдельный класс по необходимости: например, если вдруг потребуется наследование VM - CB этого к сожалению не умеет. Shocker.Proпропущено... ну вопрос-то при этом не отпадает - UC сам имеет свою VM и меняется только масштаб вопроса )Внутри каждого UC вопрос может решаться по разному, в зависимости от масштабов и особенностей каждого отдельного подвопроса. :-) С другой стороны, здесь многое решают личные предпочтения. У меня в последнее время приоритеты в сторону простоты и минимального объёма кода. Если на каждый чих делать присоединяемые свойства, как тому учат современные практики - это никак не попадает под мои критерии абсолютной правильности. :-) я общался с другим гуру XAML, так сказать со своими учителем, многие его подходы к разным способом реализации функционала и бизнес логики отличаются от моих, как он говорил, если твой подход работает, он удобен для тебя, пользуйся им :) и радуйся жизни. Можно и MVC шаблон использовать в XAML, этого ни кто не запрещает. Лично я предпочитаю, когда все XAML файлы являются просто ресурсами которые я потом использую, следовательно CodeBehind я выношу в отдельные классы которые не размазаны по форму или xaml файлу с кодом или разбиты на Partial, плюс когда нужное поведение в отдельном классе, я могу его легко повторно использовать в любой другой части и даже в другой ситуации, если он универсален. ... |
|||
:
Нравится:
Не нравится:
|
|||
13.10.2015, 14:12 |
|
Зависимости в MVVM в WPF
|
|||
---|---|---|---|
#18+
Roman MejtesЛично я предпочитаю, когда все XAML файлы являются просто ресурсами которые я потом использую, следовательно CodeBehind я выношу в отдельные классы которые не размазаны по форму или xaml файлу с кодом или разбиты на Partial,Цель не понятна, усложнения очевидны. Roman Mejtesплюс когда нужное поведение в отдельном классе, я могу его легко повторно использовать в любой другой части и даже в другой ситуации, если он универсален.UC тоже можно повторно использовать в "любой другой части и даже в другой ситуации, если он универсален". ... |
|||
:
Нравится:
Не нравится:
|
|||
13.10.2015, 14:43 |
|
Зависимости в MVVM в WPF
|
|||
---|---|---|---|
#18+
Roman MejtesПередавать события в MVVM невозможно, но совершенно спокойно можно передать делегат или предикат как свойство, через связывание. Я использую RoutedCommand и ICommand в паре. Для этого я сделал класс слушатель, он следит за автоматизируемым событием CommandExecute и CommandCanExecute и когда оно "всплывает" (так как оно бабл), вызывается связанная с этим маршрутизируемой командой, команда из модели представления (ICommand) . Всё взаимодействие из направлении из View в ViewModel идет через команды, особенно RoutedCommand вывозят в ContentPresenter'ах, списках и прочих контейрерах + кнопки + элементы меню + Application.commands. Roman Mejtes , хочу вернуться к этому вопросу. Я сейчас сам столкнулся с ситуацией, когда хочу получить одновременно поведение ICommand (то есть присоединить команду через {Binding} во ViewModel), но в то же время хочу, чтобы команда всплывала как RoutedCommand. При этом получается, что в CommandBinding я должен указать Executed="хендлер", который находится в Code Behind. Я так не понял, как ты смог прикрутить ICommand к RoutedCommand? Если ты разместил этот "слушатель" в Code Behind - это значит, что ты наследуешь все окна от какого-то своего базового класса, а не от Window? И как ты определяешь в нем, что именно является VM (чтобы передать событие)? В общем, буду признателен за примерчик Roman Mejtes2_Shocker.Pro : я тебе накидаю пример проекта и кину сюда чуток по позже, сегодня или завтра. ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2016, 20:05 |
|
Зависимости в MVVM в WPF
|
|||
---|---|---|---|
#18+
Roman Mejtesв XAML файлах кода в 99% случаев нет вообще, если он нужен он привязывается в дереве там, где необходим через Interactive или AttachedProperty. Грубо говоря, если мне нужно добавить логику Drag&Drop для панели, я создаю класс DragDropHelper, в нем прикрепляемое свойсто IsDragDropEnabled и когда его значение меняется на тру, для контрола к котому применяется значение прикрепляются все нужные мне обработчики событий. Получается, что вся логика отвечающая за Drag & Drop у меня в отдельном классе.100 раз перечитал все это, на 101-й начало немного доходить... )) Под Interactive ты имеешь ввиду поведения? То есть наследники Behavior<>? правильно я понял? В таком случае, присоединение логики через присоединяемое свойство - это почти то же самое, только лишнюю библиотеку тянуть не надо ) Но вопрос в другом - таким образом ты придаешь поведение некоторому ОДНОМУ элементу, это удобно для стандартных и относительно универсальных поведений. Но я не понял, как ты поступаешь, когда нужно наполнить форму логикой. Скажем, есть пяток-десяток кнопок, которые надо оживить и которые должны в итоге работать в едином контексте (логично бы в контексте VM). Как ты поступаешь? ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2016, 22:49 |
|
Зависимости в MVVM в WPF
|
|||
---|---|---|---|
#18+
тыц пример в проекте, в папке View XAML словари с представлением, в MainView пример CommandListener, в PersonView для кнопки Delete задана маршрутизируемая команда, в проекте нет Window вообще, запускает приложение через Application.Statup=<handler>, ActionCommand - это обычный RelayCommand, просто у меня в проектах он малость навороченный, это тут не нужно Код: xml 1. 2. 3. 4. 5. 6. 7.
<commands:CommandListener.CommandsCollection> - это обычный AttachedProperty, цеплять можно к любому <commands:CommandsCollection> - Это FreezableCollection, её необходимо создавать самому, так как AttachedProperty нельзя инициализировать сразу, commands:CommandBind - это freezble объект, у него есть 3 свойства: RoutedCommand - указывается маршрутизируемая команда, которая будет прослушиваться Command - команда которая будет вызывать в контексте ViewModel IsHandled - это свойство по умолчанию равно True, если указать False, то после того как команда обработается, она продолжит всплывать по дереву и если встретит еще 1 CommandListener то будет обработана еще раз. То есть 1 RoutedCommand можно вызвать 2 разные команды в моделях на разных уровнях, выполняться они будут конечно же в том порядке, в каком расположены в дереве снизу вверх (от ветвей к корню). ... |
|||
:
Нравится:
Не нравится:
|
|||
21.01.2016, 16:57 |
|
Зависимости в MVVM в WPF
|
|||
---|---|---|---|
#18+
ах да, как ты и просил, в проекте нет не 1 XAML файла с CodeBehind ) ... |
|||
:
Нравится:
Не нравится:
|
|||
21.01.2016, 16:58 |
|
Зависимости в MVVM в WPF
|
|||
---|---|---|---|
#18+
Shocker.Pro, авторНо вопрос в другом - таким образом ты придаешь поведение некоторому ОДНОМУ элементу, это удобно для стандартных и относительно универсальных поведений. Но я не понял, как ты поступаешь, когда нужно наполнить форму логикой. Скажем, есть пяток-десяток кнопок, которые надо оживить и которые должны в итоге работать в едином контексте (логично бы в контексте VM). Как ты поступаешь? не понял вопроса, о чем конкретно идет речь? вся логика модели, должна быть в моделе,а View её только отражать (логику). Если кнопка не должна работать, значит метод OnCanBlaBlaBla должен реализовывать это в модели для данного ICommand. Что понимается, под словом оживить? ... |
|||
:
Нравится:
Не нравится:
|
|||
21.01.2016, 17:01 |
|
Зависимости в MVVM в WPF
|
|||
---|---|---|---|
#18+
Roman Mejtes, Ага, спасибо огромное, ща буду изучать. Пока ждал ответа, сам почти сделал хелпер, который устанавливает свойство связанной модели при клике на кнопку, судя по всему, подход понял правильно. Код: xml 1. 2. 3. 4. 5.
... |
|||
:
Нравится:
Не нравится:
|
|||
21.01.2016, 17:07 |
|
Зависимости в MVVM в WPF
|
|||
---|---|---|---|
#18+
Roman MejtesShocker.Pro, авторНо вопрос в другом - таким образом ты придаешь поведение некоторому ОДНОМУ элементу, это удобно для стандартных и относительно универсальных поведений. Но я не понял, как ты поступаешь, когда нужно наполнить форму логикой. Скажем, есть пяток-десяток кнопок, которые надо оживить и которые должны в итоге работать в едином контексте (логично бы в контексте VM). Как ты поступаешь? не понял вопроса, о чем конкретно идет речь? вся логика модели, должна быть в моделе,а View её только отражать (логику). Если кнопка не должна работать, значит метод OnCanBlaBlaBla должен реализовывать это в модели для данного ICommand. Что понимается, под словом оживить?Ну, то есть в VM ты создаешь n-ное количество реализаций ICommand и привязываешь их через к кнопкам через Command="{Binding blabla}" - правильно я понял? А если у конкретного источника нет свойства Command для нужного события, ты вешаешь на него свой листенер, как показано выше, и все равно заставляешь его выполнять ICommand в VM? Правильно я понял? ... |
|||
:
Нравится:
Не нравится:
|
|||
21.01.2016, 17:11 |
|
|
start [/forum/topic.php?fid=21&msg=39074066&tid=1440434]: |
0ms |
get settings: |
8ms |
get forum list: |
15ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
172ms |
get topic data: |
13ms |
get forum data: |
3ms |
get page messages: |
71ms |
get tp. blocked users: |
2ms |
others: | 13ms |
total: | 305ms |
0 / 0 |