MVVM Привязка Ортогональных Аспектов в Представлениях, например, Параметрах настройки приложения

У меня есть приложение, которое я разрабатываю использование WPF\Prism\MVVM. Все подходит, и у меня есть некоторые приятные реализации MVVM. Однако в некоторых моих представлениях я хотел бы смочь связать параметры настройки приложения, например, когда пользователь перезагружает приложение, флажок для автопрокрутки сетки должен быть проверен в состоянии, пришло в последний раз время, чтобы пользователь использовал приложение.

Мое представление должно связать с чем-то, что содержит состояние установки "автопрокрутки". Я мог поместить это на модель представления, но настройки приложений являются ортогональными к цели модели представления. Установка "автопрокрутки" управляет аспектом представления. Эта установка является просто примером. Будет множество их и обрызгивания моих моделей представления со свойствами для представления параметров настройки приложения (таким образом, я смогу связать их), чувства решительно yucky.

Одна модель представления на представление, кажется, de rigeuer...

Что такое best\usual практика здесь?

  • Обрызгать мои модели представления с параметрами настройки приложения?
  • Имеют несколько моделей представления на представление, таким образом, настройки могут быть представлены самостоятельно?
  • Разделение просматривает так, чтобы средства управления могли связать с ApplicationSettingsViewModel? = слишком много представлений?
  • Что-то еще?

Редактирование 1

Для добавления немного большего количества контекста я разрабатываю UI с динамическим интерфейсом с вкладками. Каждая вкладка разместит единственный виджет и существует множество виджетов. Каждый виджет является составом Призмы отдельных представлений. Некоторые представления обще среди виджетов, например, представления средства выбора файла. Пока каждый виджет состоит из нескольких представлений, концептуально виджет имеет единственный набор пользовательских настроек, например, последнего выбранного файла, автопрокрутка включила и т.д. Они должны быть сохранены и retrieved\applied, когда приложение запускается снова, и представления виджета воссоздаются.

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

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

5
задан Tim Lloyd 12 May 2010 в 22:41
поделиться

3 ответа

Основная проблема здесь заключается в использовании Prism для создания подвидов, чтобы сделать виджет - подвиды слишком мелкие.

Виджет - это набор подчиненных представлений (пользовательских элементов управления), которые работают вместе, чтобы сформировать единое представление, например объединение «средства выбора файлов» и «списка сетки». Подвиды должны быть составлены с использованием простого Xaml для создания составного представления. Вы по-прежнему получаете возможность повторного использования отдельных пользовательских элементов управления, но состав виджета фиксируется во время разработки.

Теперь, когда у нас есть одно представление: WidgetView (состоящее из пользовательских элементов управления), мы можем привязать это представление к одной модели представления: WidgetViewModel. Обработка настроек для представления виджета затем обрабатывается путем составления нескольких моделей представления. Просто поместите свойство в WidgetViewModel, которое предоставляет WidgetSettingsViewModel. Пользовательские элементы управления связывают WidgetViewModel для взаимодействия с базовой моделью, но связываются с WidgetSettingsViewModel для настроек виджета.

Таким образом, мы можем привязать основную модель просмотра и модель просмотра настроек к виджету.

2
ответ дан 15 December 2019 в 06:19
поделиться

Ах, ваша редакция достаточно проясняет ситуацию, чтобы потребовать нового ответа. Вот оно:

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

В вашем случае у вас есть набор настроек, которые вы хотите связать с каждой комбинацией {user, widget}. Этот набор настроек должен быть сохранен и доступен в каждом из ваших представлений. Концептуально это отдельный объект модели: это не виджет, это не пользователь и не зависит от вида. Назовете ли вы это «моделью представления» или просто «моделью» - это в первую очередь вопрос терминологии. Как бы вы ни хотели его классифицировать, давайте назовем сам объект UserWidgetSettings .

Где-то у вас будет резервное хранилище, в котором вы будете сохранять объекты UserWidgetSettings. Это может быть локальный файл, реестр или та же база данных, где хранятся ваши объекты User и Widget. Для обсуждения предположим, что они хранятся отдельно от объектов User и Widget, и у вас есть класс, который их сохраняет:

public class UserWidgetSettings : DependencyObject // or INotifyPropertyChanged
{
  public bool AutoScroll { get { return (bool)GetValue(AutoScrollProperty); } set { SetValue(AutoScrollPropery, value); } }
  public static readonly DependencyProperty AutoScrollProperty = DependencyProperty.Register("AutoScroll", typeof(bool), typeof(UserWidgetSettings));

  ... more settings ...
}

public class UserWidgetSettingsStorage
{
  public static readonly UserWidgetSettingsStorage Current = new UserWidgetSettingsStorage();

  private Dictionary<Pair<User,Widget>, WeakReference<UserWidgetSettings>> _cache;


  public UserWidgetSettings GetSettings(User user, Widget widget)
  {
    ... code to retrieve settings from file, registry, etc ...
  }
  public void Savechanges()
  {
    ... code to iterate the cache and save back changes to UserWidgetSettings objects ...
    ... called on Application.OnExit and perhaps other times ...
  }
}

Теперь вашим ViewModels, используемым представлениями, просто требуется свойство для доступа к настройкам:

public class SomeViewModel
{
  public Widget Widget { get; set; }

  ... regular view model code ...

  public UserWidgetSettings UserSettings
  {
    get
    {
      return             UserWidgetSettingsStorage.Current.GetSettings(
          MyApp.CurrentUser, Widget);
    }
  }

}

В вашем view, вы можете использовать настройки следующим образом:

<SomeControl AutoScroll="{Binding UserSettings.AutoScroll}" />

И ваш флажок для управления этим выглядит так:

<CheckBox IsChecked="{Binding UserSettings.AutoScroll}" />

Примечание: я обнаружил, что в среднем только около 20% моих представлений действительно нуждаются в собственной модели представления. Остальные могут использовать общие свойства, предоставляемые самой моделью.Если вы обнаружите, что создаете отдельную модель представления для каждого отдельного представления, что-то может быть не так. Вы можете взглянуть и посмотреть, есть ли какие-то вещи, которые вы делаете в модели представления, которые имели бы такой же или больший смысл в самой модели. Итог: хорошо спроектированные объекты модели могут значительно сократить объем кода в приложении WPF.

0
ответ дан 15 December 2019 в 06:19
поделиться

Я обнаружил, что проще всего выполнить привязку напрямую к параметрам приложения, например:

 <CheckBox IsChecked="{Binding SomeSetting,
                       Source={x:Static myAppProperties:Settings.Default}}" />

Предполагается, что вы используете функцию параметров приложения System.Configuration, предоставляемую файлами Visual Studio ".settings". Если вы используете какой-либо другой механизм для сохранения ваших настроек, этот метод все равно будет работать: просто выставьте настройки вашего пользователя и приложения на статическом объекте и выполните привязку к нему.

Если у вас есть диалоговое окно «Параметры» с множеством настроек приложения, вы можете упростить его, используя объект «Настройки» в качестве контекста данных:

<DockPanel DataContext="{Binding Source={x:Static myAppProperties:Settings.Default}}">
  ...
  <CheckBox IsChecked="{Binding SomeSetting}" />
  ...

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

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

1
ответ дан 15 December 2019 в 06:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: