Составные шаблоны данных ресурса модуля WPF (Prism)
Учитывая, что у меня есть приложение оболочки и несколько отдельных проектов модулей с использованием Microsoft CompoisteWPF (Prism v2)...
При получении команды модуль создает новый 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>
Это хорошо, но это означает, что по мере создания новых модулей необходимо добавить файл App.xaml. То, что я ищу, - это способ для модулей, поскольку они загружаются для динамического добавления в Application.Resources. Возможно ли это?
Ответы
Ответ 1
Внутри инициализации каждого модуля вы можете добавить ресурсы приложения:
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"))
});
});
}
Ответ 2
Чтобы ваше приложение оболочки не узнало о том, что ваши модули и ваши модули не попали в оболочку, я бы предоставил интерфейс для ваших модулей следующим образом:
IMergeDictionaryRegistry
{
void AddDictionaryResource(Uri packUri);
}
Вы запросите этот интерфейс в своем модульном коде:
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;
});
}
}
И наконец, в вашем Bootstrapper ConfigureContainer:
public override void ConfigureContainer()
{
base.ConfigureContainer();
Container.RegisterType<IMergeDictionaryRegistry, MergeDictionaryRegistry>();
}
Это даст вам необходимую функциональность, и ваша оболочка и ваш модуль останутся независимыми друг от друга. Это дает дополнительное преимущество, потому что вам больше не нужно проверять код Application
, чтобы проверить код модуля (просто издевайтесь IMergeDictionaryRegistry
, и все готово).
Сообщите нам, как это происходит для вас.
Ответ 3
Это похоже на большую работу!
Лично я просто объявляю словарь ресурсов в моем представлении 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>
Вы бы объявили свои шаблоны данных там, я думаю.
НТН.