Переключение между режимом просмотра и режимом редактирования в MVVM?

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

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

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

когда пользователь открывает объект, он обычно должен быть TextBlocks, Labels (или readonly TextBoxes) и т. д., и если он нажимает "редактировать" (если у него есть разрешение), он должен перейти в режим редактирования, и все метки полей должны быть инвертированы в текстовые поля (RichTextBoxes и т. д., ComboBoxes или любые другие редактируемые поля, которые не являются просто метками).

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

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

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

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

5 ответов


использовать 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;

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

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

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


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


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

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

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

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

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

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


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

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

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

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

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