WinUI3应用无法引用类库中CustomControl自定义样式问题排查
我在项目中创建了多个CustomControl,包含两个项目:
- 存放CustomControl的ClassLibrary类库;
- 引用该类库的WinUI应用。
在类库中创建了名为Badge的CustomControl,Visual Studio自动在Themes文件夹下的Generic.xaml中为其生成了带示例Control Template的默认Style。
我为该控件定义了多个样式并放入BadgeStyle.xaml文件,随后在Generic.xaml中将其作为MergedDictionary引入:
<ResourceDictionary xmlns:customControls="using:BSN.Kava.UI.SDK.CustomControls"> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="ms-appx:///BSN.Kava.UI.SDK/CustomControls/BadgeStyle.xaml" /> </ResourceDictionary.MergedDictionaries> <Style TargetType="customControls:Badge" BasedOn="{StaticResource BadgeBase}" /> </ResourceDictionary>
我期望WinUI3主应用能使用这些样式,但无法实现,必须在App.xaml的资源字典中直接引用BadgeStyle.xaml才行。
奇怪的是,以下代码无需直接引用BadgeStyle.xaml就能正常工作:
<Style TargetType="customControls:Badge" BasedOn="{StaticResource BadgeBase}" />
但其他样式均无法生效,请问问题出在哪里?
核心原因
WinUI 3中,类库的Generic.xaml仅会自动加载控件的默认样式(即无x:Key、仅指定TargetType的样式),通过MergedDictionaries引入的其他带x:Key的命名资源,主应用的资源上下文无法自动识别。
你看到的BasedOn="{StaticResource BadgeBase}"能生效,是因为这个BadgeBase是默认样式的基础,且当前Style是Badge的默认样式(无x:Key,TargetType匹配),所以Generic.xaml加载时能找到它;但其他带x:Key的样式,主应用无法自动获取类库中Generic.xaml合并字典里的资源。
解决方法
显式声明类库资源字典
在类库的AssemblyInfo.cs中添加特性,让主应用识别类库包含的资源:[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "BSN.Kava.UI.SDK.CustomControls")] [assembly: ThemeInfo( ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly )]同时确保
BadgeStyle.xaml的生成操作设置为Page,路径引用无误。主应用全局引用资源字典
在主应用的App.xaml中统一合并类库的资源字典,让所有资源全局可访问:<Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="ms-appx:///BSN.Kava.UI.SDK/CustomControls/BadgeStyle.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Application.Resources>检查样式引用逻辑
确认BadgeStyle.xaml中的其他样式已正确设置x:Key,主应用使用时需通过StaticResource对应引用:<!-- BadgeStyle.xaml中的自定义样式 --> <Style x:Key="BadgeWarningStyle" TargetType="customControls:Badge" BasedOn="{StaticResource BadgeBase}"> <!-- 样式内容 --> </Style> <!-- 主应用中使用样式 --> <customControls:Badge Style="{StaticResource BadgeWarningStyle}" />
内容的提问来源于stack exchange,提问作者RezaNoei

