能否在非WPF应用中使用ResourceDictionary与UserControl?
首先明确回答你的核心问题:完全可以在非WPF宿主应用(比如CAD插件)中使用WPF的UserControl和ResourceDictionary,但你遇到的错误是由于非独立WPF环境下的资源加载上下文问题,以及WPF运行时初始化不充分导致的。下面具体分析原因并给出解决步骤:
错误原因解析
你遇到的XamlParseException嵌套NotImplementedException,主要有两个常见诱因:
- WPF运行时未完全初始化:独立WPF应用会自动初始化
Application上下文,但CAD插件作为类库运行在非WPF宿主中,可能缺少必要的WPF环境初始化。 - 资源URI加载上下文不匹配:
pack://application:,,,/URI是针对独立WPF应用设计的,它指向宿主程序的资源上下文,而插件作为类库,资源加载的上下文和独立应用不同,直接在XAML中使用这个URI可能导致资源无法正确定位。
具体解决方案
1. 确保WPF运行时初始化
在插件启动或者UserControl构造函数的最开始,先检查并初始化WPF的Application上下文:
// 在UserControl构造函数或插件初始化代码中添加 if (System.Windows.Application.Current == null) { // 创建临时Application实例,初始化WPF运行时 new System.Windows.Application(); }
注意:部分CAD宿主可能对创建Application实例有限制,如果出现异常,可以尝试仅调用System.Windows.Application.LoadComponent来触发必要的初始化,而不创建完整的Application对象。
2. 改用代码方式加载资源字典
避免在XAML中直接引用资源字典,改为在代码中手动加载,这样可以更精准地控制资源加载上下文。修改你的UserControl构造函数如下:
public YourCustomUserControl() { // 初始化WPF运行时 if (System.Windows.Application.Current == null) { new System.Windows.Application(); } // 逐个加载Material Design资源字典 var lightThemeDict = new ResourceDictionary { Source = new Uri("pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Light.xaml", UriKind.Absolute) }; var defaultsDict = new ResourceDictionary { Source = new Uri("pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml", UriKind.Absolute) }; var primaryColorDict = new ResourceDictionary { Source = new Uri("pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Primary/MaterialDesignColor.DeepPurple.xaml", UriKind.Absolute) }; var accentColorDict = new ResourceDictionary { Source = new Uri("pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Accent/MaterialDesignColor.Lime.xaml", UriKind.Absolute) }; // 将资源字典添加到UserControl的资源集合中 Resources.MergedDictionaries.Add(lightThemeDict); Resources.MergedDictionaries.Add(defaultsDict); Resources.MergedDictionaries.Add(primaryColorDict); Resources.MergedDictionaries.Add(accentColorDict); // 最后调用InitializeComponent InitializeComponent(); }
同时,记得把XAML中的UserControl.Resources部分移除,避免重复加载导致冲突。
3. 验证依赖库的部署
确保Material Design相关的NuGet包(MaterialDesignThemes和MaterialDesignColors)已经正确安装到你的插件项目中,并且所有依赖的dll文件(比如MaterialDesignThemes.Wpf.dll、MaterialDesignColors.dll)都被复制到插件的输出目录,或者CAD宿主能够找到这些dll(比如放在宿主的插件目录下)。
4. 确认宿主的WPF控件支持
如果你的CAD宿主基于WinForms框架,需要将WPF的UserControl包装在ElementHost控件中再嵌入到宿主UI中。不过你提到之前插件运行正常,这一步可能已经处理,但如果后续仍有UI显示问题,可以检查这一点。
总结
非WPF宿主环境下使用WPF的UserControl和ResourceDictionary是完全可行的,核心是要处理好WPF运行时的初始化,以及适配类库环境的资源加载方式。按照上面的步骤调整后,应该可以解决你遇到的初始化错误。
内容的提问来源于stack exchange,提问作者paranamix2

