[WPF] UserControl и MVVM
От: vers  
Дата: 02.04.11 12:24
Оценка:
Задача: UserControl, который содержит некоторый шаблон с тремя кнопками и ContentPresenter. Этот UserConrol регистрирует DependencyProperty типа Boolean с названием IsSimpleMode, от которого должно зависеть отображение кнопок: true — отображается только первая кнопка, false — отображаются только вторая и третья кнопки. Из основного окна, содержащего элемент, происходит привязка к другим свойствам элемента, таким как Visibility и Width, а также настраивается содержимое ContentPresenter. Дополнительное требование — использование MVVM.

Сначала попробовал сделать так:
— первая кнопка Visibility="{Binding Button1Visibility}", вторая — Visibility="{Binding Button2Visibility}", третья — Visibility="{Binding Button3Visibility}";
— в конструкторе: DataContext = new ViewModel(...);
— в классе ViewModel сделал три свойства: Button1Visibility, Button2Visibility и Button3Visibility, которые, в сущности, являются конвертерами значения IsSimpleMode.

Но в таком варианте не работала привязка данных к другим свойствам UserControl в том окне, в котором он был размещен:
<uc:MyUC Visibility="{Binding MyUcVisibility}" Width="{MyUcWidth}" />
потому что DataContext в конструкторе элемента установлен на совсем другой объект. Если переустановить привязку:
<uc:MyUC DataContext="{Binding}" Visibility="{Binding MyUcVisibility}" Width="{MyUcWidth}" />
то не работает привязка внутри элемента.

Была еще идея создавать экземпляр ViewModel в ресурсах элемента:
<vm:ViewModel x:Key="vm" />
а затем делать привязку к его полям, указывая полный путь к ресурсу, но это выглядит как очень громоздкое решение.

Может, есть какие-либо другие более простые способы?
Re: [WPF] UserControl и MVVM
От: Sinix  
Дата: 02.04.11 12:35
Оценка:
Здравствуйте, vers, Вы писали:

V>Задача: UserControl, который содержит некоторый шаблон с тремя кнопками и ContentPresenter. Этот UserConrol регистрирует DependencyProperty типа Boolean с названием IsSimpleMode, от которого должно зависеть отображение кнопок: true — отображается только первая кнопка, false — отображаются только вторая и третья кнопки.

Я бы заменил на enum и использовал бы стили с DataTrigger-ами для кнопок. Если надо — конвертеры.

Заводить для этого всякие Button1Visibility и тем более выносить знания о поведении UI за границы контрола — имхо, изврат и чрезмерное усложнение из чистой любви к паттернам ради паттернов.
Re: [WPF] UserControl и MVVM
От: Codechanger Россия  
Дата: 02.04.11 15:32
Оценка: -1
Здравствуйте, vers, Вы писали:
V>Может, есть какие-либо другие более простые способы?

Есть. Включить мозг, например.
Re[2]: [WPF] UserControl и MVVM
От: vers  
Дата: 02.04.11 16:19
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Заводить для этого всякие Button1Visibility и тем более выносить знания о поведении UI за границы контрола — имхо, изврат и чрезмерное усложнение из чистой любви к паттернам ради паттернов.


Я привел упрощенный пример, на деле там гораздо сложнее. Но выносить поведение элемента за пределы его класса нужно для последующего модульного тестирования, таково требование заказчика проекта (прощу прощения за то, что забыл упомянуть об этом заранее).

S>Я бы заменил на enum и использовал бы стили с DataTrigger-ами для кнопок.


Я думал над таким вариантом, но не нашел способа сделать триггер для свойства зависимостей, которое определено в этом же классе.

S>Если надо — конвертеры.


Конвертеры точно подойдут, но заказчик против, поскольку эту логику уже не получится протестировать при помощи модульных тестов.
Re[2]: [WPF] UserControl и MVVM
От: vers  
Дата: 02.04.11 16:20
Оценка:
Здравствуйте, Codechanger, Вы писали:

V>>Может, есть какие-либо другие более простые способы?


C>Есть. Включить мозг, например.


Спасибо, Вы очень помогли.
Re[3]: [WPF] UserControl и MVVM
От: Sinix  
Дата: 02.04.11 16:42
Оценка:
Здравствуйте, vers, Вы писали:

V>Я привел упрощенный пример, на деле там гораздо сложнее. Но выносить поведение элемента за пределы его класса нужно для последующего модульного тестирования, таково требование заказчика проекта (прощу прощения за то, что забыл упомянуть об этом заранее).


В таком случае лучше отказаться от UserControl и перейти к обычному контролу + VisualStateManager. Ну или остаться с MVVM и фактически дублировать функционал WPF, а затем ещё его и тестировать.

S>>Я бы заменил на enum и использовал бы стили с DataTrigger-ами для кнопок.

V>Я думал над таким вариантом, но не нашел способа сделать триггер для свойства зависимостей, которое определено в этом же классе.

RelativeSource = Self. Первое нагугленное —
http://stackoverflow.com/questions/4298529/style-datatrigger-with-reference-to-type-of-parent-control
Без обид, но без глубокого знания WPF к MVVM лучше и не подходить — очень уж легко нагородить костылей на ровном казалось бы месте.

V>Конвертеры точно подойдут, но заказчик против, поскольку эту логику уже не получится протестировать при помощи модульных тестов.

Я крайне скептически отношусь к тестам для UI, тем более если предлагается городить несколько сотен строк кода ради замены пары строк в ксамле. У меня такие тесты так и не окупились.

Если так хочется сделать тест — кто запрещает просто создать контрол, установить нужные свойства, а затем проверить состояние элементов ч/з VisualTreeHelper? Будет всяко надёжней, чем тестировать отдельные куски.
Re: [WPF] UserControl и MVVM
От: Vladek Россия Github
Дата: 02.04.11 18:11
Оценка:
Здравствуйте, vers, Вы писали:

V>Задача: UserControl, который содержит некоторый шаблон с тремя кнопками и ContentPresenter. Этот UserConrol регистрирует DependencyProperty типа Boolean с названием IsSimpleMode, от которого должно зависеть отображение кнопок: true — отображается только первая кнопка, false — отображаются только вторая и третья кнопки. Из основного окна, содержащего элемент, происходит привязка к другим свойствам элемента, таким как Visibility и Width, а также настраивается содержимое ContentPresenter. Дополнительное требование — использование MVVM.



V>Может, есть какие-либо другие более простые способы?


DataContext контрола должен быть привязан к модели, соответственно все биндинги для данных из модели, в том числе и для свойства IsSimpleMode. А описанная проблема решается в коде контрола без всяких хитроумных биндингов, в обработчике OnIsSimpleModePropertyChanged, который указывается при создании этого зависимого свойства через вызов DependencyProperty.Register.
Re[2]: [WPF] UserControl и MVVM
От: vers  
Дата: 02.04.11 19:07
Оценка:
Здравствуйте, Vladek, Вы писали:

V>А описанная проблема решается в коде контрола без всяких хитроумных биндингов, в обработчике OnIsSimpleModePropertyChanged, который указывается при создании этого зависимого свойства через вызов DependencyProperty.Register.


Правильно ли я понимаю, что в этом случае вообще не будет биндингов, а свойства элементов будут устанавливаться в коде с обращениям по их именам?
Re[4]: [WPF] UserControl и MVVM
От: vers  
Дата: 02.04.11 19:19
Оценка:
Здравствуйте, Sinix, Вы писали:

S>В таком случае лучше отказаться от UserControl и перейти к обычному контролу + VisualStateManager.


Снова прошу прощения, забыл указать еще одно ограничение: .NET Framework 3.5 SP1. Заказчик хочет, чтобы приложение работало в Windows 7 без установки .NET Framework 4 (четкостью рендеринга текста переубедить его не удалось).

V>>Я думал над таким вариантом, но не нашел способа сделать триггер для свойства зависимостей, которое определено в этом же классе.

S>RelativeSource = Self. Первое нагугленное -
S>http://stackoverflow.com/questions/4298529/style-datatrigger-with-reference-to-type-of-parent-control
S>Без обид, но без глубокого знания WPF к MVVM лучше и не подходить — очень уж легко нагородить костылей на ровном казалось бы месте.

Да, действительно, Вы правы, перечитаю Мак-Дональда. За плечами около десяти WPF-проектов, но DataTrigger ни разу не использовал, всегда обходился набором Trigger/MultiTrigger/EventTrigger.
Такой вариант подходит, спасибо.

S>Я крайне скептически отношусь к тестам для UI, тем более если предлагается городить несколько сотен строк кода ради замены пары строк в ксамле. У меня такие тесты так и не окупились.


Да, я тоже такого рода тесты выношу на уровень интеграционного тестирования.
Re[3]: [WPF] UserControl и MVVM
От: Vladek Россия Github
Дата: 02.04.11 20:58
Оценка:
Здравствуйте, vers, Вы писали:

V>Здравствуйте, Vladek, Вы писали:


V>>А описанная проблема решается в коде контрола без всяких хитроумных биндингов, в обработчике OnIsSimpleModePropertyChanged, который указывается при создании этого зависимого свойства через вызов DependencyProperty.Register.


V>Правильно ли я понимаю, что в этом случае вообще не будет биндингов, а свойства элементов будут устанавливаться в коде с обращениям по их именам?


Да.
Re[5]: [WPF] UserControl и MVVM
От: Sinix  
Дата: 03.04.11 03:30
Оценка:
Здравствуйте, vers, Вы писали:

V>Снова прошу прощения, забыл указать еще одно ограничение: .NET Framework 3.5 SP1. Заказчик хочет, чтобы приложение работало в Windows 7 без установки .NET Framework 4 (четкостью рендеринга текста переубедить его не удалось).


Оххх, тогда советовать особо нечего. Можно конечно извратиться с вебинсталлером или включать 45 мб дистрибутива в инсталлер, или понадеяться на win update, но заказчик, очевидно, не поймёт. А жаль, помимо улучшенного рендеринга в 4м WPF пофиксено очень много багов.

S>>Я крайне скептически отношусь к тестам для UI, тем более если предлагается городить несколько сотен строк кода ради замены пары строк в ксамле. У меня такие тесты так и не окупились.


V>Да, я тоже такого рода тесты выношу на уровень интеграционного тестирования.

Но заказчик требует юнит-тесты? Охх, что ещё сказать?

Удачи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.