System.Windows.Media.Brush во ViewModel
От: Fortnum  
Дата: 06.06.11 15:12
Оценка:
Здравствуйте, Sinix, Вы писали
Автор: Sinix
Дата: 30.01.11
:

S>Ну и не надо втаскивать знания об UI в прочие слои. Зачем оно там?


Кстати, может ли и должен ли ViewModel определять цвет? А если этот цвет часть предметной области? Если он приходит из данных, из БД, например? А если из БД приходит Thickness и Visibility элемента UI? Какой великий смысл ограничивать себя и не втаскивать знания об UI в слой моделей вида? Какую задачу решает это ограничение? По-моему, чисто пуристскую. Автоматизированному тестированию моделей видов это вовсе не мешает. Использованию дизайнером альтернативных источников данных о том же цвете тоже. Аналогично и с фокусом.
Re: Имхо
От: Qbit86 Кипр
Дата: 06.06.11 15:26
Оценка:
Здравствуйте, Fortnum, Вы писали:

S>>Ну и не надо втаскивать знания об UI в прочие слои. Зачем оно там?


Вью-модел всяко ближе ко вью, чем к модели. Фактически, он в том же слое, что и вью. Это сугубо «технический» артефакт, призванный упростить эксплуатацию такого средства WPF как data binding.

F>Кстати, может ли и должен ли ViewModel определять цвет?


Не должен (для этого есть стили всякие, дататриггеры, etc), но может. Сам же Джош Смит писал, что вью-модел вполне можно использовать как «конвертер на стероидах». Скажем, у тебя в модели есть enum типа { Message, Warning, Error }, где-то во вью-моделе ему может соответствовать поле с цветом, принимающим значение { Blue, Yellow, Red } — это поле уже готово для привязки, имеет целевой тип и ему не нужны конвертеры для интерпретации. Исходный enum может как храниться во вью-моделе, так и нет (если да, то не все поля будут устанавливаться независимо, будут «ведущие» и «ведомые» поля).
Глаза у меня добрые, но рубашка — смирительная!
Re[2]: Имхо
От: Fortnum  
Дата: 06.06.11 15:40
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>Не должен (для этого есть стили всякие, дататриггеры, etc), но может. Сам же Джош Смит писал, что вью-модел вполне можно использовать как «конвертер на стероидах». Скажем, у тебя в модели есть enum типа { Message, Warning, Error }, где-то во вью-моделе ему может соответствовать поле с цветом, принимающим значение { Blue, Yellow, Red } — это поле уже готово для привязки, имеет целевой тип и ему не нужны конвертеры для интерпретации. Исходный enum может как храниться во вью-моделе, так и нет (если да, то не все поля будут устанавливаться независимо, будут «ведущие» и «ведомые» поля).


Вот и я пришел к тому же. Только продолжая эту мысль я взял и написал ViewModel, к примеру, окна. И ViewModel меню. И т.п. базовые ViewModel'и. Далее, когда я делаю какой-то бизнес-ViewModel, я его либо наследую от одного из этих базовых, либо составляю его из этих базовых. В результате у меня получается, что слой ViewModel — это тот же View-слой, только без отображения.

Почему-то повсеместно встречаю противоречие:
1. UI (View) надо отделить от слоя ViewModel, чтобы если что, можно было спокойно натянуть другой UI, по другой технологии (как это сделал по ссылке в ТС Sinix).
2. Надо стараться (бояться) втаскивать знания об UI в слой ViewModel (опять же, в том же сообщении у Sinix'а).

Это не только у него. Это, повторюсь, повсеместно. А у меня крыша едет от такого противоречия ))

Почему плохо делать как я? — Да, я как бы во второй раз, только в слое ViewModel, изображаю контрол. Но разве вы так не делаете, вынося туда IsSelected и т.п. свойства? Почему нельзя тупо для каждого lookless- и user-контрола из слоя View беззастенчиво писать его "теневую" контролирующую копию в слое ViewModel. Ну и пофиг, что я вношу во ViewModel знания о UI — главное, что мне не приходится каждый раз переписывать эти ViewModel'и — они у меня в общей библиотеке как горячие пирожки. И новый класс ViewModel я пишу комбинируя уже существующие классы ViewModel'ей, как бы представляя себе UserControl, каким он должен быть, либо подстраиваясь под уже нарисованный эскиз. Что тут плохого, никак не пойму? ViewModel, по-моему, имеет гарантированное право знать все о UI и управлять им. Единственное что, ViewModel должен уметь это делать в физическое отсутствие самого этого UI. Попробую через n-е время выложить сэмпл — никаких ограничений нет, никаких проблем (может мне кажется?) — спокойно меняю интерфейс WPF на WinForms и обратно, не модифицируя ни капельки тот же ViewModel слой. Где подвох?
Re[3]: Имхо
От: Qbit86 Кипр
Дата: 06.06.11 15:54
Оценка:
Здравствуйте, Fortnum, Вы писали:

F>1. UI (View) надо отделить от слоя ViewModel, чтобы если что, можно было спокойно натянуть другой UI, по другой технологии (как это сделал по ссылке в ТС Sinix).


Я вообще скептически отношусь к отторжению от первого представления модели этого вида, и приклеивание этой модели вида ко второму представлению. Даже если технология одинаковая, вид может быть просто другим «срезом» модели.

Скажем, есть у тебя во вью-моделе упомянутое выше свойство. Согласно одним — оно должно отражать состояние модели, как минимум быть того же типа, например, enum LogEntryType. Согласно другим — оно должно выражаться в терминах близких ко вью, уже готовых для привязки, т.е. иметь тип System.Windows.Media.Brush. И вот тебе надо создать другой вид — на той же технологии, просто по-другому скомпонованный — а в нём вовсе не отражено обсуждаемое свойство. Получается, что в (пере)используемой модели вида хранится какое-то левое свойство. А если у тебя один вид отражает свойства модели 1 и 2, второй вид свойства 2 и 3, третий вид свойства 1 и 3, то вью-модел, получается, должен отражать все эти три свойства? И с ростом количества требуемых видов он будет разбухать?
Глаза у меня добрые, но рубашка — смирительная!
Re[4]: Имхо
От: Fortnum  
Дата: 06.06.11 17:24
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>Я вообще скептически отношусь к отторжению от первого представления модели этого вида, и приклеивание этой модели вида ко второму представлению. Даже если технология одинаковая, вид может быть просто другим «срезом» модели.

Q>Скажем, есть у тебя во вью-моделе упомянутое выше свойство. Согласно одним — оно должно отражать состояние модели, как минимум быть того же типа, например, enum LogEntryType. Согласно другим — оно должно выражаться в терминах близких ко вью, уже готовых для привязки, т.е. иметь тип System.Windows.Media.Brush. И вот тебе надо создать другой вид — на той же технологии, просто по-другому скомпонованный — а в нём вовсе не отражено обсуждаемое свойство. Получается, что в (пере)используемой модели вида хранится какое-то левое свойство. А если у тебя один вид отражает свойства модели 1 и 2, второй вид свойства 2 и 3, третий вид свойства 1 и 3, то вью-модел, получается, должен отражать все эти три свойства? И с ростом количества требуемых видов он будет разбухать?

Ну, во-первых, в самом разбухании ничего страшного нет. Само деление приложения на уровни так его разбухает, что использовать ViewModel'и не "в обтяжку" по видам — это ничего криминального.
Во-вторых, я говорю не о разбухании для использования одной модели между двумя и более видами. Несколько иное имею в виду я. Я имею в виду, что есть уже некие базовые, проверенные и оттестированные ViewModel-и, комбинируя которые или наследуясь от которых, ты создаешь свои. Например, ViewModel для элемента списка будет включать свойство IsSelected, и чтобы создать свой ViewModel для элемента списка, ты либо наследуешь свой ViewModel от этого базового, либо включаешь экземпляр этой базовой ViewModel в качестве свойства своей ViewModel. ControlTemplate-ы, соответственно, тоже можно использовать уже готовые, с заранее прописанными биндингами к этим стандартным ViewModel-ям. Готовые, это не значит немодифицируемые — в готовые Template-ы можно вставлять свои суб-контролы, которые ты уже можешь модифицировать как тебе надо. При желании можно внешний стандартный шаблон посредством изменения свойств в соответствующих готовых ViewModel'ях, к которым они прибиндены, сделать "прозрачными" визуально.

Хочу продемонстрировать... попробую накатать поэтапные примеры — необходимо выслушать критику
Re[5]: Имхо
От: Экселенц Россия  
Дата: 07.06.11 07:29
Оценка:
Fortnum, я вас правильно понял, что вы по сути для каждого визуального контрола написали соответствующую ему маленькую ViewModel (TextBoxViewModel, DataGridViewModel, ComboBoxViewModel и т.д.) и ViewModel всего окна является комбинацией таких маленьких ViewModel-ей? Хотелось бы действительно глянуть на пример вашего подхода, по-моему, он очень интересен.
Re[6]: Имхо
От: Fortnum  
Дата: 07.06.11 07:53
Оценка:
Здравствуйте, Экселенц, Вы писали:

Э>Fortnum, я вас правильно понял, что вы по сути для каждого визуального контрола написали соответствующую ему маленькую ViewModel (TextBoxViewModel, DataGridViewModel, ComboBoxViewModel и т.д.) и ViewModel всего окна является комбинацией таких маленьких ViewModel-ей? Хотелось бы действительно глянуть на пример вашего подхода, по-моему, он очень интересен.


Да, именно так. Я начал с того, что мне надо было сохранять положения и группировку клиентских окон через веб-сервис, который в свою очередь сохранял их положение в базе данных. Ну и еще несколько примеров, когда управление состоянием UI становится не дизайнерской, а чисто бизнес-задачей (возможно я вообще и не прав). Выносить весь этот код по общению с веб-сервисом в уровень View мне показалось неправильным, и я подумал, почему бы тупо не отзеркалить каждый используемый мной контрол на уровень ViewModel, а уж будет к соответствующей ViewModel биндится View или не будет — это уже не столь важно — ViewModel, в любом случае, заставить View это делать, не может. Сейчас я еще немного поизучаю, что народ придумал в этом отношении, чтобы не дай бог не изобрести велосипед, подготовлю и опубликую примеры.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.