.NET MAUI后置代码获取StaticResource提示资源不在字典解决方法
XAML中{StaticResource Secondary}能正常引用,是因为XAML标记扩展的资源查找逻辑会自动沿「控件实例→当前页面→应用全局」的层级,逐级遍历所有合并资源字典匹配键值。你在后台直接调用Resources["Secondary"]只会查找当前MainPage自身声明的本地资源字典,不会向上遍历应用级资源,会抛出如下异常:
System.Collections.Generic.KeyNotFoundException: 'The resource 'Secondary' is not present in the dictionary
之前直接取App.Current.Resources.MergedDictionaries.First()拿到的字典所有值为null,是因为应用级MergedDictionaries会按加载顺序存放多个资源字典(包括Colors.xaml、Styles.xaml、系统内置样式字典等),直接取第一个字典根本不是存Secondary颜色的Colors.xaml字典。
方法1:调用内置查找方法(优先推荐)
MAUI所有可视化元素都自带TryFindResource方法,会自动走完整个资源查找链路,不需要手动遍历字典,也不需要关心资源具体存放在哪个合并字典中,只要在InitializeComponent()调用之后使用即可:
private Button BtnAdd(int btnNum) { Button btn = new Button(); btn.Text = "TestButton " + btnNum; btn.HorizontalOptions = LayoutOptions.Center; btn.WidthRequest = 125; btn.HeightRequest = 125; // 自动沿资源层级查找Secondary键 if (btn.TryFindResource("Secondary", out var colorObj)) { btn.BorderColor = colorObj as Color; } btn.BorderWidth = 5; btn.Margin = new Thickness(5, 5, 5, 5); btn.Clicked += TestBTN; return btn; }
如果在非可视化类的代码中查找资源,直接调用Application.Current.TryFindResource("Secondary", out var colorObj)即可,效果完全一致。
方法2:手动遍历合并字典(适配特殊场景)
如果需要手动定位资源所在的字典,不要硬编码取MergedDictionaries的固定索引,遍历所有字典逐个匹配即可:
Color secondaryColor = null; // 先遍历所有合并字典 foreach (var dict in App.Current.Resources.MergedDictionaries) { if (dict.TryGetValue("Secondary", out var val)) { secondaryColor = val as Color; break; } } // 部分资源可能直接挂载在根资源字典,未放入合并字典,需要补查 if (secondaryColor == null) { App.Current.Resources.TryGetValue("Secondary", out var rootVal); secondaryColor = rootVal as Color; }
关于需要传入VisualElement的静态类方案说明
这类方案本质是对资源逐级查找逻辑的封装,传入VisualElement是为了确定资源查找的起始节点,从传入控件开始沿父级链路向上查找。如果只需要找全局应用级资源,直接传入Application.Current即可,不需要传入页面或控件实例。
- 所有资源查找操作必须放在
InitializeComponent()调用之后执行,此时资源字典才完成初始化,否则会出现找不到资源或取到null的问题 - 不要用固定索引取MergedDictionaries中的元素,不同MAUI版本、不同项目的资源加载顺序可能变化,硬编码索引会导致版本兼容问题
内容的提问来源于stack exchange,提问作者Nicolas Oñate

