2009-07-23 5 views
13

Учитывая то, что у меня есть приложение оболочки и несколько отдельных проектов модулей с использованием Microsoft CompoisteWPF (Prism v2) ...Композитный WPF (Prism) модуль ресурсов шаблоны данных

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

var viewModel = _container.Resolve<IMyViewModel>(); 
_regionManager.Regions[RegionNames.ShellMainRegion].Add(viewModel); 

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

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:vm="clr-namespace:Modules.Module1.ViewModels" 
    xmlns:vw="clr-namespace:Modules.Module1.Views" 
> 
    <DataTemplate DataType="{x:Type vm:MyViewModel}"> 
     <vw:MyView /> 
    </DataTemplate> 
</ResourceDictionary> 

Edit:

я могу заставить его работать, добавляя к App.xaml

<Application.Resources> 
    <ResourceDictionary.MergedDictionaries> 
     <ResourceDictionary Source="pack://application:,,,/Module1;component/Module1Resources.xaml"/> 
     <ResourceDictionary Source="pack://application:,,,/Module2;component/Module2Resources.xaml"/> 
    </ResourceDictionary.MergedDictionaries> 
</Application.Resources> 

Что это хорошо, но это означает, что новые модули созданы, приложение. Файл xaml должен быть добавлен. То, что я ищу, - это способ для модулей, поскольку они загружаются для динамического добавления в Application.Resources. Это возможно?

ответ

5

В инициализации каждого модуля, вы можете добавить к ресурсам приложения:

Application.Current.Resources.MergedDictionaries 
       .Add(new ResourceDictionary 
       { 
        Source = new Uri(
         @"pack://application:,,,/MyApplication.Modules.Module1.Module1Init;component/Resources.xaml") 
       }); 

Или, если вы будете следовать условность каждого модуля есть словарь ресурсов под названием «Resources.xmal» ...

protected override IModuleCatalog GetModuleCatalog() 
{ 
    var catalog = new ModuleCatalog(); 

    AddModules(catalog, 
       typeof (Module1), 
       typeof(Module2), 
       typeof(Module3), 
       typeof(Module4)); 

    return catalog; 
} 

private static void AddModules(ModuleCatalog moduleCatalog, 
    params Type[] types) 
{ 
    types.ToList() 
     .ForEach(x => 
      { 
       moduleCatalog.AddModule(x); 
       Application.Current.Resources.MergedDictionaries 
        .Add(new ResourceDictionary 
           { 
            Source = new Uri(string.Format(
                 @"pack://application:,,,/{0};component/{1}", 
                 x.Assembly, 
                 "Resources.xaml")) 
           }); 
       }); 
} 
+0

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

19

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

IMergeDictionaryRegistry 
{ 
    void AddDictionaryResource(Uri packUri); 
} 

You «d задать для этого интерфейса в коде модуля:

public class MyModule : IModule 
{ 
    IMergeDictionaryRegistry _merger; 
    public MyModule(IMergeDictionaryRegistry merger) 
    { 
      _merger = merger; 
    } 

    public void Initialize() 
    { 
      _merger.AddDictionaryResource(new Uri("pack://application:,,,/Module1;component/Module1Resources.xaml"); 
    } 
} 

Вы бы затем осуществить это в вашей оболочке, чтобы сделать это:

public MergeDictionaryRegistry : IMergeDictionaryRegistry 
{ 
    public void AddDictionaryResource(Uri packUri) 
    { 
      Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary() 
      { 
       Source = packUri; 
      }); 
    } 
} 

И, наконец, в ConfigureContainer вашей Bootstrapper в:

public override void ConfigureContainer() 
{ 
    base.ConfigureContainer(); 
    Container.RegisterType<IMergeDictionaryRegistry, MergeDictionaryRegistry>(); 
} 

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

Сообщите нам, как это пойдет вам.

+0

Спасибо. WPF знает, как визуализировать ViewModel с помощью DataTemplate (см. Http://msdn.microsoft.com/en-us/magazine/dd419663.aspx#id0090097). Проблема заключается в том, что приложение узнает о DataTemplate в другой сборке. Я отредактировал сообщение, чтобы предоставить более подробную информацию. – Oll

+0

О, я понимаю, что вы делаете. Возможно, вам придется предоставить некоторый интерфейс (IMergeDictionaryRegistration с методом, который принимает URL-адрес пакета), в ваши модули и добавить их в словарь ресурсов вашего приложения. Просто теория. –

+0

Также ... Мне любопытно, как это происходит для вас. Дайте нам знать. Это интересный подход. –

1

Это похоже на работу!

Лично я просто объявить словарь ресурсов в UserControl.Resources разделе с моей точки зрения как это ...

<UserControl.Resources> 
    <ResourceDictionary Source="../Resources/MergedResources.xaml" /> 
</UserControl.Resources> 

Это слиты словарь затем указывает на какие-либо ресурсы, мне нужно включить.

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
<ResourceDictionary.MergedDictionaries> 
    <ResourceDictionary Source="Iconography.xaml" /> 
    <ResourceDictionary Source="Typeography.xaml" /> 
</ResourceDictionary.MergedDictionaries> 

Вы бы объявить шаблоны данных там я думаю.

HTH.

 Смежные вопросы

  • Нет связанных вопросов^_^