.NET8中如何访问控件隐式样式?SetterSpecificity权限问题
问题
自定义控件需要在内部获取其隐式设置的样式,但受限于SetterSpecificity的访问权限,无法直接实现。此前在.NET7中通过反射方式实现了需求,但升级到.NET8后该方法失效,出现与SetterSpecificity相关的访问问题。
.NET7中可用的实现代码
XAML页面代码
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:MauiApp1" x:Class="MauiApp1.MainPage"> <ContentPage.Resources> <Style TargetType="local:CustomButton"> <Setter Property="HorizontalOptions" Value="Center" /> <Setter Property="VerticalOptions" Value="Center" /> <Setter Property="BackgroundColor" Value="Bisque" /> <Setter Property="FontSize" Value="18" /> </Style> </ContentPage.Resources> <local:CustomButton Text="Hello World!!" FontSize="18" HorizontalOptions="Center" /> </ContentPage>
C#自定义控件代码
using Microsoft.Maui.Controls; using System.Reflection; namespace MauiApp1 { public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); } } public class CustomButton : Button { public CustomButton() { this.Clicked += CustomButton_Clicked; } private void CustomButton_Clicked(object sender, EventArgs e) { var dynamicResources = (Dictionary<BindableProperty, string>)typeof(Element)?.GetRuntimeProperties()?.FirstOrDefault(x => x.Name == "DynamicResources")?.GetValue(this); var key = dynamicResources?.Keys.FirstOrDefault(); var style = (Style)this.GetValue(key); } } }
.NET8兼容的解决方案
由于.NET8对内部API的访问限制更严格,反射方式不再适用。可以通过遍历控件的资源层级,合法获取隐式样式:
using Microsoft.Maui.Controls; namespace MauiApp1 { public class CustomButton : Button { public CustomButton() { Clicked += CustomButton_Clicked; } private void CustomButton_Clicked(object sender, EventArgs e) { var implicitStyle = GetImplicitStyleForControl(); // 在这里使用获取到的隐式样式 } private Style GetImplicitStyleForControl() { Element currentElement = this; // 从控件自身向上遍历父元素的资源字典 while (currentElement != null) { if (currentElement.Resources.TryGetValue(typeof(CustomButton), out var resource) && resource is Style style) { return style; } currentElement = currentElement.Parent; } // 最后检查应用级资源 if (Application.Current?.Resources.TryGetValue(typeof(CustomButton), out var appResource) == true && appResource is Style appStyle) { return appStyle; } return null; } } }
说明
该方法通过遍历控件的父级资源链(从自身到页面再到应用),查找匹配自定义控件类型的隐式样式,完全依赖公开API,不存在内部成员访问权限问题,同时兼容.NET7和.NET8版本。
内容的提问来源于stack exchange,提问作者Tamizh
相关产品推荐
相关产品推荐

