![](/img/trans.png)
[英]How to add ResourceDictionary in Bootstrapper Application
[英]How to use the Application ResourceDictionary to do RuntimeType mapping
我正在尝试在应用程序的ResourceDictionary中将一个(ViewModel)RuntimeType映射到另一个(View)RuntimeType。 这样,我的Controller类就可以查找ViewModel对象类,并将其绑定到适当的View类的新实例。 该应用程序被实现为插件的集合,这意味着在编译时不知道映射。
在我的沙箱应用程序(用于原型设计)中,将映射添加到主Window的资源字典中,如下所示:
<Window.Resources>
<!-- This template associates the ConfirmDialog type
with the ConfirmDialogViewModel type. -->
<x:Type TypeName="v:ConfirmDialog" x:Key="{x:Type vm:ConfirmDialogViewModel}" />
</Window.Resources>
这可以编译并完美运行,并且DependencyProperty使用映射来显示ConfirmDialog窗口,以查找正确的类并在附加的ViewModel更改时实例化该类。
但是,当我尝试将相同的映射放入应用程序的Resource字典中时,会引发异常:
System.Xaml.dll中发生类型为'System.Xaml.XamlObjectWriterException'的第一次机会异常
发生System.Windows.Markup.XamlParseException
HResult = -2146233087消息='“ RuntimeType”对象上缺少键值。 行号“ 20”和行位置“ 14”。
来源= PresentationFramework LineNumber = 20 LinePosition = 14
StackTrace:位于System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader,IXamlObjectWriterFactory writerFactory,布尔skipJournaledProperties,对象rootObject,XamlObjectWriterSettings设置,Uri baseUri)
InnerException:System.Xaml.XamlObjectWriterException HResult = -2146233088 Message ='缺少“ RuntimeType”对象上的键值。 行号“ 20”和行位置“ 14”。 来源= System.Xaml
该资源包含在App.xaml中,如下所示:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- This resource file contains the DataTemplates. -->
<ResourceDictionary Source="Resources/DataTemplates.Resources.xaml" />
<!-- This resource file contains the Styles. -->
<ResourceDictionary Source="Resources/Styles.Resources.xaml" />
<!-- This section is used for mapping Views to ViewModels. -->
<ResourceDictionary>
<!-- This template associates the ConfirmDialog type
with the ConfirmDialogViewModel type. -->
<x:Type TypeName="v:ConfirmDialog" x:Key="{x:Type vm:ConfirmDialogViewModel}" />
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
关于Window和Application ResourceDictionary对象为何行为不同,如何从异常中查找更多信息或我可能尝试解决的任何建议。
我的解决方案是向项目添加一个新的ResourceDictionary XAML文件,并将其作为MergedDictionary包括在内。
Mappings.Resources.xaml(名称空间已更改):
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:v="clr-namespace:MyWpfViewNamespace"
xmlns:vm="clr-namespace:MyViewModelNamespace;assembly=MyViewModelAssembly"
>
<!-- This template associates the ConfirmDialog type
with the ConfirmDialogViewModel type. -->
<x:Type TypeName="v:ConfirmDialog" x:Key="{x:Type vm:ConfirmDialogViewModel}" />
</ResourceDictionary>
App.xaml(摘录):
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- This resource file contains the DataTemplates. -->
<ResourceDictionary Source="Resources/DataTemplates.Resources.xaml" />
<!-- This resource file contains the Styles. -->
<ResourceDictionary Source="Resources/Styles.Resources.xaml" />
<!-- This resource file contains the RuntimeType mappings. -->
<ResourceDictionary Source="Resources/Mappings.Resources.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
并且(如果有人感兴趣),实例化是在DependencyProperty的PropertyChanged事件处理程序中完成的,该事件处理程序绑定了一个将接口暴露给顶级ViewModel基类的对象。
在Mappings.Resources.xaml映射类型中:
ShowModalViewProperty.cs(摘录):
public static void ShowModalViewPropertyChanged(
DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
var window = d as Window;
ITopLevelViewModel newValue = e.NewValue as ITopLevelViewModel;
if ((null != window) && (null != newValue))
{
// Search the local and Application resources for a mapping
// between the ViewModel type of the new property and a
// View type to use to display it.
Type typeOfViewModel = newValue.GetType();
Type typeOfView = (Type)window.TryFindResource(typeOfViewModel);
if (null == typeOfView)
{
typeOfView = (Type)Application.Current.TryFindResource(typeOfViewModel);
}
// If a concrete type of the correct class is available...
if ((null != typeOfView)&&
(!typeOfView.IsAbstract)&&
(typeOfView.IsSubclassOf(typeof(BaseWpfWindow))))
{
// Create a new window and show it as a (modal) dialog.
BaseWpfWindow dialogWindow = (BaseWpfWindow)
Activator.CreateInstance(typeOfView);
if (null != dialogWindow)
{
dialogWindow.Owner = window;
dialogWindow.DataContext = newValue;
// ModalResult is a Property of ITopLevelViewModel, used to return
// the Window.DialogResult back to the ViewModel object.
newValue.ModalResult = dialogWindow.ShowDialog();
}
}
}
}
我仍然不知道为什么单独的MergedDictionary方法有效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.