如何让WPF独立视图项目设计时共享主项目App.xaml资源?
解决WPF独立视图项目设计时无法加载主项目App.xaml资源的问题
问题场景
我的WPF应用采用主项目(MyApp)与独立视图项目(MyApp.Views)分离的结构:
- 主项目MyApp包含
App.xaml,并已引用MyApp.Views项目 - MyApp.Views项目存放所有UserControl、资源字典等UI内容
主项目的App.xaml已通过合并资源字典引用视图项目的资源:
<Application x:Class="MyApp.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="pack://application:,,,/MyApp.Views;component/Resources/Icons.xaml" /> <ResourceDictionary Source="pack://application:,,,/MyApp.Views;component/Resources/Styles.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Application.Resources> </Application>
运行时应用正常,但在设计视图中打开MyApp.Views里的UserControl(如下方示例)时,会提示"The resource "Some Icon" could not be resolved"类错误:
<UserControl x:Class="MyApp.Views.AddressBarView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> <Grid> <Button> <Image Source="{StaticResource MyIcon}" /> </Button> </Grid> </UserControl>
当前临时方案是给每个UserControl单独添加资源引用,但不想重复编写这段代码。
原因分析
WPF设计器加载独立视图项目的UserControl时,默认上下文是视图项目本身,不会自动加载主项目App.xaml中的全局资源,因此设计时无法解析主项目中定义的资源引用。
解决方案
方法一:创建共享资源字典+基类UserControl
这种方法通过统一的基类实现资源复用,无需逐个修改UserControl:
- 在MyApp.Views项目中创建
SharedResources.xaml资源字典,合并所有需要共享的资源:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="/MyApp.Views;component/Resources/Icons.xaml" /> <ResourceDictionary Source="/MyApp.Views;component/Resources/Styles.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary>
- 创建基类
BaseView.xaml,在其资源中引用上述共享字典:
<UserControl x:Class="MyApp.Views.BaseView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <UserControl.Resources> <ResourceDictionary Source="/MyApp.Views;component/SharedResources.xaml" /> </UserControl.Resources> </UserControl>
- 所有业务UserControl均继承
BaseView,即可自动获取共享资源。
方法二:配置视图项目的设计时应用程序
给视图项目指定一个设计时专用的App资源配置,让设计器加载时使用该配置:
- 在MyApp.Views项目中添加
DesignTimeApp.xaml(无需编写后台代码),内容模仿主项目的资源引用:
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="/MyApp.Views;component/Resources/Icons.xaml" /> <ResourceDictionary Source="/MyApp.Views;component/Resources/Styles.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Application.Resources> </Application>
- 右键MyApp.Views项目 → 属性 → 生成 → 在“设计时”区域的“应用程序定义”下拉框中选择
DesignTimeApp.xaml。
设置完成后,设计器加载视图项目的UserControl时会自动使用这个设计时应用程序的资源,解决设计时资源找不到的问题。
方法三:使用设计时属性快速指定资源
如果不想创建基类或修改项目配置,可以给每个UserControl的根元素添加d:DesignResources属性,仅在设计时生效:
<UserControl x:Class="MyApp.Views.AddressBarView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800" d:DesignResources="/MyApp.Views;component/SharedResources.xaml"> <!-- 原有内容不变 --> </UserControl>
该属性仅影响设计时,不会对运行时产生任何影响。
内容的提问来源于stack exchange,提问作者Alexander
相关产品推荐
相关产品推荐

