Шаблоны данных ресурсов составного модуля WPF (Prism)
-
19-09-2019 - |
Вопрос
Учитывая, что у меня есть приложение оболочки и несколько отдельных проектов модулей, использующих 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>
Редактировать:
Я могу заставить его работать, добавив в 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.Это возможно?
Решение 2
При инициализации каждого модуля вы можете добавить к ресурсам приложения:
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"))
});
});
}
Другие советы
Чтобы вашему приложению оболочки не нужно было ничего знать о ваших модулях, а ваши модули не могли каким-либо образом обращаться к оболочке, я бы предоставил интерфейс для ваших модулей следующим образом:
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;
});
}
}
И, наконец, в Конфигураторе вашего загрузчика:
public override void ConfigureContainer()
{
base.ConfigureContainer();
Container.RegisterType<IMergeDictionaryRegistry, MergeDictionaryRegistry>();
}
Это даст вам желаемую функциональность и ваша оболочка и ваш модуль останутся независимыми друг от друга.Это имеет дополнительное преимущество: его легче тестировать, поскольку вам не нужно раскручивать Application
чтобы протестировать код вашего модуля (просто издевайтесь IMergeDictionaryRegistry
и все готово).
Дайте нам знать, как это происходит для вас.
Кажется, что все это требует много работы!
Лично я просто объявляю словарь ресурсов в моем представлении. 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>
Я думаю, вы бы объявили там свои шаблоны данных.
ХТХ.