2010-03-05 3 views
2

Используя шаблон MVVM, создающий приложения WPF, у вас есть ViewModel, предоставляющий данные для представления. Я встретил ситуацию, когда мне кажется разумным создавать объекты WPF в моей модели ViewModel, а View извлекает их и показывает их. Более конкретно, у меня есть функциональность для рисования, где мне нужно сохранить InkPresenter в конце. Я получаю жесты мыши в кодовом представлении представления, но передаю события в ViewModel. ViewModel обрабатывает событие мыши и создает объекты чертежа, которые помещаются в ObservableCollection таким образом, что View может извлекать их и отображать их.Работа с объектами WPF внутри ViewModel

Вопрос в том, это нормально, или это плохая практика для создания объектов WPF в классах ViewModel? И почему? Если все в порядке; существуют ли какие-либо рекомендации или рекомендации по работе с этими объектами?

ответ

2

Нет, это «не нормально» (цитаты, поскольку я говорю о лучших методах, говоря, что ViewModel не является ViewModel, потому что он делает это так же неправильно) для создания и ссылки на классы WPF (Control-) внутри ваших ViewModels.

При попытке удалить ViewModel очень большие недостатки. Элементы управления нуждаются в специальных обработках и представляют собой нежелательные зависимости.

Вы должны передать фактические «данные» этих объектов в ViewModel: для примера с InkPresenter это будет O.k. по-моему, отправить ViewModel StylusPoints, но не сам InkPresenter. Еще лучше будут классы ViewModel, представляющие StylusPoints, - они могут быть сопоставлены с фактическими StylusPoints путем привязки данных (я не знаю, возможно ли это с помощью InkPresenter) или через некоторые медиаторы (например, с помощью подключенных свойств).

Для создания вы можете использовать некоторый посредник, который вы передаете, например. ViewModels и который затем создает подходящий WPF-Control и устанавливает VM как свой DataContext.

+0

Спасибо за ваше мнение. Я согласен с тобой. Я пытаюсь избежать элементов управления WPF в ViewModels, но иногда это намного проще. – stiank81

+0

Не могли бы вы сказать, что наличие ViewModel обеспечивает ... скажем, GradientBrush также нарушает «правила»? – Kilhoffer

+0

Лично я бы сказал, что все по-другому. Кисть можно рассматривать как объект данных и может быть полезной и значимой для предоставления ViewModel View. Как вы думаете? – stiank81

2

Я столкнулся с интересным случаем для этого только сегодня. Я создаю пользовательский интерфейс, который включает коллекцию FlowDocument. Эти элементы представлены в ListView, один из шаблонов которых - RichTextBox.

Первая проблема, с которой я столкнулся, заключается в том, что свойство RTB Document не является свойством зависимостей, поэтому вы не можете привязываться к нему. К счастью, какой-то бесстрашный разработчик там столкнулся с этой проблемой, прежде чем я это сделал, и реализовал подкласс RichTextBox с Document overriden в качестве свойства зависимостей.

Все было хорошо и хорошо, пока я не реализовал переустановку перетаскивания коллекции. Здесь я обнаружил одну из причин , почемуDocument не является DP. Изменение порядка коллекции фактически не изменяет порядок объектов, к которым они привязаны; элементы, которые перемещаются, просто обновляют свои привязывающие объекты. И слава, если FlowDocument принадлежит к одному RichTextBox, вы не можете назначить его другому. Переупорядочение этих нарушает пользовательский интерфейс, что является проблемой, потому что вся причина, по которой я делаю этот интерфейс, в первую очередь, состоит в том, чтобы переупорядочить эти элементы.

Молот, который я решил поразить, состоял в том, чтобы сделать RichTextBox объектом моей модели. Таким образом, когда я перемещаю FlowDocuments в коллекции, RTB, которые владеют ими, перемещаются вместе с ними.

Лично я не даю ни малейшего доказательства того, является ли этот класс проверяемым единицей. Это не то, что делает это неправильным ответом.

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

Я не совсем уверен, какой правильный ответ в моем случае еще будет. Я думаю, что мне, возможно, придется исправить мою привязанную RichTextBox, так что она поддерживает объектыFlowDocument: тот, который выставлен миру своим Document геттером и сеттером, и тот, который находится внутри самого элемента управления. (То есть, когда что-то устанавливает свойство Document на объект, оно сохраняет это значение в своем личном поле, а затем копирует содержимое документа в содержимое базы Document.)

Это очень длинный путь говоря: «Создание объектов WPF в модели представления кажется сейчас довольно плохой идеей, когда я это делаю».

+0

На самом деле кажется плохой идеей держать объекты WPF в ViewModel. В моем случае я мог бы заставить его работать - пока. Но я могу представить, что я могу легко столкнуться с проблемами, если мне нужно изменить что-то, связанное с этим позже. – stiank81

Смежные вопросы