Переключение между режимом просмотра и режимом редактирования в MVVM? - PullRequest
9 голосов
/ 07 февраля 2011

Я новичок в MVVM, и я решил двигаться дальше и начать применять его в своих будущих проектах.

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

Я хочу, чтобы все представления в моем проекте имели 2 режима: режим редактирования и режим просмотра.
Я не хочу, чтобы пользователь по умолчанию видел TextBoxes для всех полей, я скорее хочу, чтобы они видели TextBlocks (или устанавливали все свойства TextBoxe s 'как IsReadOnly в true (через стиль и т. Д., Как вы мне сказали). .).

Когда пользователь открывает сущность, это обычно должны быть TextBlocks, Labels (или TextBoxes только для чтения) и т. Д., И если он нажимает «Edit» (если у него есть разрешение), он должен перейти в режим редактирования и все поля. 'метки должны быть инвертированы в TextBoxes (RichTextBoxes и т. д., ComboBoxes или любые другие редактируемые поля, которые не являются просто метками).

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

Пожалуйста, отошлите мне хорошую статью, в которой объясняется, как это сделать (возможно, это делается Visual State ?? IDK).

UPDATE
Я хочу знать, ЧТО, а не КАК, мой вопрос о шаблоне, и я должен отделить режим редактирования из режима просмотра на V или VM? Поэтому, пожалуйста, подчеркните эту деталь в своем ответе.

Заранее спасибо.

Ответы [ 5 ]

10 голосов
/ 07 февраля 2011

Используйте свойство IsReadOnly для текстовых полей и свяжите его со свойством "режим редактирования":

<TextBox .... IsReadOnly={Binding IsViewMode} ... />

Тогда на ваш взгляд модель:

public bool IsViewMode
{
    get { return _IsViewMode; }
    set
    {
        _IsViewMode= value;
        // Call NotifyPropertyChanged when the source property is updated.
        NotifyPropertyChanged("IsViewMode");
    }
}

IsViewMode по умолчанию true и переключается на false, когда пользователь нажимает «изменить». Привязка мгновенно сделает все текстовые поля редактируемыми.

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

Чтобы поменять текстовые блоки и ваши элементы управления, вам нужно иметь оба элемента управления, совместно использующих одно и то же местоположение в сетке, и их видимость, управляемую свойством IsViewMode через пару преобразователей:

<TextBlock Grid.Row="1" Grid.Column="2" ...
           Visiblity={Binding IsViewMode, Converter=DirectConverter} ... />
<ComboBox Grid.Row="1" Grid.Column="2" ...
          Visiblity={Binding IsViewMode, Converter=InvertedConverter} ... />

Прямой преобразователь:

return IsViewMode ? Visibility.Visible : Visibility.Collapsed;

Инвертированный преобразователь:

return IsViewMode ? Visibility.Collapsed : Visibility.Visible;
3 голосов
/ 07 февраля 2011

Ответ ChrisF в порядке, если вы хотите пойти по маршруту IsReadOnly.Однако если вы хотите пойти по пути TextBlock-to-TextBox, наиболее эффективным способом является использование элемента управления, который переключает свой шаблон с помощью триггеров на основе значения свойства IsInEditMode или IsInViewModel.

3 голосов
/ 07 февраля 2011

Я думаю об этом следующим образом: представление - это то, как оно выглядит, а модель представления - как он взаимодействует с пользователем. Поскольку интерфейс «только для чтения» ведет себя существенно иначе, чем интерфейс чтения / записи, то должны быть две разные модели ViewModel.

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

С другой стороны, если у вас есть более сложный бизнес-процесс (или рабочий процесс), который вы моделируете, то, как правило, способ манипулирования информацией сильно отличается от способа ее просмотра. Поэтому я обычно разделяю две модели ViewModel, если только это не CRUD.

2 голосов
/ 07 февраля 2011

Во-первых, я бы реализовал абстрактный базовый класс для моих моделей представлений, которые реализовали IEditableObject и предоставили соответствующие команды для BeginEdit, EndEdit и CancelEdit. Возможно, что фактические реализации для этих трех методов должны соответствовать производным классам, но команды могут жить в базовом классе.

В этом подходе EndEdit обновляет модель текущими значениями свойств в модели представления.

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

Что касается визуального дизайна внешнего интерфейса, я нахожу идею о том, что представление только для чтения - это просто представление редактирования с элементами управления только для чтения - это то, что в первую очередь нравится программистам. Вообще говоря, если вы просто представляете объект пользователю, цель этой презентации - предоставить пользователю информативное, четкое и интуитивно понятное представление информации в этом объекте. Если вы позволяете пользователю редактировать объект, цель этой презентации состоит в том, чтобы сделать задачу изменения всех редактируемых свойств объекта максимально простой и понятной.

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

2 голосов
/ 07 февраля 2011

Viewmodel: я бы определенно оставил только одну viewmodel со свойством ViewMode, как описано в ответе ChrisF. Отдельные ViewModels были бы просто не элегантными.

Просмотр: На мой взгляд, у вас есть как минимум три варианта, с различными плюсами и минусами.

  1. Просто прочитайте все элементы управления, как указано в ответе ChrisF. Плюсы: самое простое. Минусы: по моему скромному мнению, это ужасный интерфейс.

  2. Создание отдельных дисплеев и редактирование элементов управления в отдельных контейнерах. Привязать видимость контейнеров к ViewMode. Плюсы: более приятный пользовательский интерфейс может быть предоставлен здесь. Вы даже можете анимировать переходы от одного к другому. Минусы: удваивает количество элементов управления (может ухудшить производительность для очень больших окон). Расположение элементов управления внутри двух контейнеров в точно одинаковых позициях пикселей может стать немного нетривиальным в пользовательском интерфейсе жидкости.

  3. Для каждого элемента редактирования в xaml расположите элемент управления дисплеем прямо над ним. Привязать видимость к свойству ViewMode. Плюсы: по крайней мере, нет дублирования элементов управления метками, поэтому немного быстрее. Минусы: сложнее получить анимацию и другие настройки для просмотра.

Редактировать: С учетом предоставленного пояснения я решил заменить предыдущий ответ, поскольку он в значительной степени касался вопросов как, а не как.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...