Стратегия поиска ViewModel, когда представления являются иерархическими и их нужно менять местами - PullRequest
1 голос
/ 27 сентября 2011

Допустим, я создаю навигационную систему для автомобиля:

  • Главное окно будет содержать экран, кнопки режима и регулятор громкости.
  • В зависимости отВ режиме системы на экране будет отображаться панель аудио, климат или навигация.
  • В режиме аудио будет другой набор кнопок режима и панель, которая может отображать радио, CD илиЭлементы управления MP3.

Моя стратегия для таких соглашений в прошлом состояла в том, чтобы модели моего представления следовали точно такой же иерархии, что и представления.Итак:

  • MainViewModel будет иметь ScreenViewModel.
  • ScreenViewModel будет иметь AudioViewModel, ClimateViewModel и NavigationViewModel.Он также будет иметь свойство CurrentViewModel, которое будет установлено на модель представления аудио, климата или навигации, в зависимости от режима системы.
  • AudioViewModel будет аналогична ScreenViewModel, содержащей модели представления для каждого изрежимы аудиосистемы (радио, CD и MP3), а также свойство для сохранения модели представления для текущего режима.

XAML для привязки представления к модели представления будет выглядеть примерно так:это:

<Window.Resources>
    <DataTemplate DataType="{x:Type vm:AudioViewModel}">
        <view:AudioPanel />
    </DataTemplate>
    <DataTemplate DataType="{x:Type vm:ClimateViewModel}">
        <view:ClimatePanel />
    </DataTemplate>
    <DataTemplate DataType="{x:Type vm:NavigationViewModel}">
        <view:NavigationPanel />
    </DataTemplate>
</Window.Resources>

<ContentControl Content="{Binding CurrentViewModel}" />

Если пользователь прослушивает радио и решает ввести пункт назначения в навигационную систему, он нажимает кнопку режима навигации.В MainWindowViewModel будет команда, которая изменяет системный режим на «Navigation» и устанавливает CurrentViewModel в NavigationViewModel.Это приведет к замене NavigationView. Очень чистое решение.

К сожалению, несмотря на то, что такие действия хорошо работают в режиме выполнения, они ломаются при попытке работать с подчиненным представлением (скажем, AudioPanel) в Expression Blend, потому что модель родительского представления (MainWindowViewModel) не существует дляпредоставить AudioViewModel.

Решение, которое, кажется, поддерживается в наборах инструментов, таких как MVVM Light и Simple MVVM, состоит в том, чтобы вместо этого использовать ViewModelLocator, а затем установить представление в свой собственный DataContext путем привязки к правильному свойству локатора.,Затем локатор обслуживает экземпляр модели представления.

«Способ выполнения ViewModelLocator» решает проблему «проектируемости», но мне не ясно, как представлять иерархические отношения и обрабатывать переключение одного представлениядля другого.Концептуально, для меня просто имеет смысл иметь модель представления, содержащую модели дочернего представления.Он правильно представляет иерархию представлений, замена представлений выполняется очень просто, и если представление больше не требуется, связанная модель представления и все ее подчиненные будут подвергаться сборке мусора путем простого удаления ссылки на родительский элемент.

Вопрос

Какова наилучшая практика для создания ViewModelLocator для обработки иерархических представлений, обмена представлениями в зависимости от режима системы и удаления представлений?

В частности:

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

Ответы [ 2 ]

1 голос
/ 28 сентября 2011

Оказывается, в Visual Studio / Blend есть атрибут дизайна XAML, который позволяет вам установить время разработки DataContext элемента.Это применимо только во время разработки, поэтому должна быть возможность продолжить подключение DataContext с использованием шаблонов данных (т. Е. ViewModelLocator или ViewManager могут вообще не понадобиться).

Например, скажем, у вас естьпредставление с именем AudioPanel и модель представления с именем AudioViewModel.

. Вам просто нужно инициализировать некоторые данные времени разработки в AudioViewModel ...

public class AudioViewModel : ViewModelBase
{
    public int Volume { get; set; }
    public AudioMode Mode { get; set; }
    public ViewModelBase ModePanelViewModel { get; set; }

    public AudioViewModel()
    {
        if (IsInDesignMode)
        {
            Volume = 5;
            Mode = AudioMode.Radio;
            ModePanelViewModel = new RadioViewModel();
        }
    }
}

... Затем, по вашему мнению, вам просто нужно объявить атрибут d:DataContext ...

<UserControl x:Class="NavSystem.Views.AudioPanel"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:vm="clr-namespace:NavSystem.ViewModels"
             mc:Ignorable="d"
             d:DataContext="{d:DesignInstance vm:AudioViewModel, IsDesignTimeCreatable=True}">

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

Подробнее об этом см. в этом блоге: http://karlshifflett.wordpress.com/2009/10/28/ddesigninstance-ddesigndata-in-visual-studio-2010-beta2/

1 голос
/ 27 сентября 2011

Похоже, что текущее представление в иерархии представлений является частью представления «состояние», поэтому оно будет иметь собственную сущность «модель» (viewmodel), которая управляет этими отношениями. Я бы не использовал для этого контейнер IoC, но я бы использовал его для регистрации фабрики, которую «менеджер представлений» использует для создания «подвидов».

...