Prism MVVM - добавление дочернего представления к родительскому представлению без использования областей и внедрения, только XAML

Я новичок в Silverlight и шаблоне MVVM / Prism, так что это может быть глупый вопрос.

У меня есть представление, в котором есть настраиваемые элементы управления. Эти настраиваемые элементы управления на самом деле тоже являются представлениями, и для их управления используются модели представления.

В настоящее время для добавления этих «дочерних» представлений к представлению, которое я использую (см. Рис. 1), а затем в модели представления у меня есть метод Initialise (), который разрешает дочернее представление и вводит его (см. Рис. 2).

Рис.1

<UserControl
x:Class="ProjectA.Module.Screens.Views.PlatformScreenView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Regions="clr-namespace:Microsoft.Practices.Composite.Presentation.Regions;assembly=Microsoft.Practices.Composite.Presentation"
>
<Grid x:Name="LayoutRoot">
    <ContentControl
        Regions:RegionManager.RegionName="FeaturesSelectionControl"
        />
</Grid>

Fig.2

public void Initialise()
{
    IRegion featuresRegion = _regionManager.Regions["FeaturesSelectionControl"];
    featuresRegion.Add(_container.Resolve<IFeatureSelectionControlViewModel>().View);
}

У меня вопрос: нужно ли делать это для каждого элемента управления, который я хочу добавить? Я понимаю, почему это работает таким образом, но это похоже на довольно много кода, а также мне нужно отслеживать все имена регионов и следить за тем, чтобы у меня не было конфликтов и т. Д. Есть ли более простой способ сделать это без регионов и только в XAML?

Я видел фрагмент XAML на StackOverflow здесь но не знаю, как это работает и хочу ли я -

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

Любая помощь очень ценится.

Джеймс


person jameskind    schedule 07.01.2010    source источник
comment
Я отредактировал свой ответ после вашего разъяснения. Надеюсь, это соответствует вашим потребностям.   -  person Anderson Imes    schedule 07.01.2010
comment
Я отредактировал свой ответ после вашего другого комментария. Я не понимал, что ваша проблема связана с немного меньшим объемом родительских и дочерних представлений.   -  person Anderson Imes    schedule 07.01.2010


Ответы (1)


Редактировать после уточнения:

Похоже, вы вообще не хотите использовать RegionManager, и это нормально. Я бы предложил следующее:

Создайте интерфейс для ваших модулей, который будет использоваться для регистрации методов создания представлений:

public interface IViewRegistry
{
     void RegisterMainView(Func<object> ViewCreationDelegate);
}

Ваши модули будут использовать это так:

public MyModule : IModule
{
     IViewRegistry _registry;
     public MyModule(IViewRegistry registry)
     {
          _registry = registry;
     }

     public void Initialize()
     {
          _registry.RegisterMainView(() =>
          {
               var vm = new MyViewModel();
               var view = new MyView();
               var view.DataContext = vm;
               return view;
          });
     }
}

Затем в своей оболочке вы сначала реализуете реестр представлений (это упрощение ... вам, вероятно, понадобится что-то более надежное)

public ViewRegistry : IViewRegistry
{
     public static List<Func<object>> ViewFactories
     {
           get { return _viewFactories; }
     }
     static List<Func<object>> _viewFactories = new List<Func<object>>();
     public void RegisterMainView(Func<object> viewFactory)
     {
          _viewFactories.Add(viewFactory);
     }
}

И, наконец, вот как ваша оболочка это покажет. Вот сначала его ViewModel:

public ShellViewModel : ViewModel
{
     public ObservableCollection<object> MainViews
     {
          ...
     }

     public ShellViewModel()
     {
          MainViews = new ObservableCollection<object>(ViewRegistry.Select(factory => factory()));
     }
}

А вот и ваш View (смотри, ма, без RegionManager!):

<UserControl ...>
   <Grid>
     <ItemsControl ItemsSource="{Binding MainViews}" />
   </Grid>
</UserControl>

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


Дальнейшие правки:

После еще нескольких комментариев от OP, я думаю, я понимаю, что OP просто хочет показать представление в другом представлении без использования RegionManager. Похоже, OP использует RegionManager для отображения каждого представления на экране, что, вероятно, является излишним.

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

<UserControl x:Class="Views.MyParentView" ...>
<StackPanel>
     <TextBlock>Blah blah blah some other stuff... blah blah</TextBlock>
     <myViews:AddressView DataContext="{Binding AddressVM}" />
</StackPanel>
</UserControl>

А вот viewModel родительского представления:

public ParentViewModel : ViewModel
{
     public AddressViewModel AddressVM
     {
          ...
     }

     public ParentViewModel()
     {
          AddressVM = new AddressViewModel();
     }
}

Вот и все. Это избавит вас от необходимости слишком много работать, чтобы показать эти представления.

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

person Anderson Imes    schedule 07.01.2010
comment
Я не думал, что этот тип DataTemplate работает в Silverlight? Однако я не проверял Sliverlight 4.0. пока что. - person David Padbury; 07.01.2010
comment
Дерьмо, ты меня поймал. Я не заметил, как слово Silverlight как-то наклеено на весь ваш пост. Моя ошибка. Затем вы, вероятно, захотите использовать докладчика ... метод, который вы представили в своем сообщении ‹ContentControl Content = {Binding SmartFormViewModel} /›, будет работать только с DataTemplating, поэтому я пошел в этом направлении в своем ответе. Я немного подумаю и сделаю репост. - person Anderson Imes; 07.01.2010
comment
Привет, Андерсон! Спасибо за ответ, но я не думаю, что это то, что мне нужно. Возможно, мой вопрос недостаточно ясен, я в конечном итоге стремлюсь к тому, чтобы не использовать регионы. Похоже, что нужно приложить много усилий, чтобы определить область с именем, убедиться, что это имя не конфликтует с существующим именем, а затем написать немного C # для подключения View к этой области. Я из фона ASP.NET, и если я хочу разместить пользовательский элемент управления на странице, я просто добавляю его в разметку ASP.NET. Возможно ли это в SL и MVVM? Я надеюсь, что это имеет смысл, и еще раз спасибо за любую помощь. - person jameskind; 07.01.2010
comment
Конечно, вам не обязательно использовать регионы. Вы можете просто иметь доступную коллекцию представлений и привязать к ней свое главное представление. Это то, что вы хотите? Я выложу пример. Я не понял, что вы не хотите использовать RegionManager. - person Anderson Imes; 07.01.2010
comment
Да, я думаю, что хочу. Может быть, пример поможет мне лучше сформулировать то, чего я пытаюсь достичь - скажем, у меня был очень простой пользовательский элемент управления «почтовый адрес» (состоящий из модели, модели представления и представления), который я использовал на различных экранах Silverlight. Каждый раз, когда я хотел использовать этот элемент управления, приходилось ли мне определять регион в XAML, а затем вводить его с помощью RegionManager на C #? Это рекомендуемый способ добавления пользовательских элементов управления в MVVM? - person jameskind; 07.01.2010
comment
Это действительно зависит от вас. Есть много способов снять шкуру с этой кошки. Я думаю, что для вашего конкретного случая это, наверное, излишество. Для таких простых вещей нет причин не объявлять статически ваш пользовательский элемент управления для вашего представления и связывать его с моделью представления, которая является свойством вашей более крупной модели представления для представления. Если это больше похоже на то, что вы хотите, я могу опубликовать небольшой образец и по этому поводу. - person Anderson Imes; 07.01.2010
comment
Блестяще! Ваше последнее редактирование с помощью AddressView отлично ответило на мою проблему. Извините, мне потребовалось столько попыток, чтобы внятно объяснить, что я хотел! Ваш комментарий о том, что использование регионов только для пользовательских элементов управления является чрезмерным, именно поэтому я поднял этот вопрос, и решение на самом деле очень простое, но, как я уверен, вы знаете, что трудно найти свой путь, когда вы начинаете новая технология / выкройка. Большое спасибо за ваше время, мы очень ценим его. - person jameskind; 07.01.2010
comment
Рад, что смог помочь! Вы были правы, считая, что это слишком сложно. Надеюсь, я достаточно просто объяснил, когда использовать каждую стратегию, но дайте мне знать, если это недостаточно ясно. - person Anderson Imes; 07.01.2010