.NET Maui 如何通过C#代码创建RadioButton的ControlTemplate
以下是将你提供的XAML模板完整转换为C#代码的实现,完全匹配原模板的视觉样式和状态切换逻辑:
步骤1:构建ControlTemplate的视觉树
先创建模板的根容器和内部控件结构:
// 创建根Border var rootBorder = new Border { Stroke = Color.FromArgb(255, 243, 242, 241), // #F3F2F1 StrokeThickness = 0, StrokeShape = new RoundRectangle { CornerRadius = new CornerRadius(10) }, BackgroundColor = Colors.Transparent, HorizontalOptions = LayoutOptions.Start, VerticalOptions = LayoutOptions.Start }; // 创建内部Grid var innerGrid = new Grid { Margin = new Thickness(5) }; innerGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); innerGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }); // 创建单选按钮图标容器Grid var iconGrid = new Grid { GridColumn = 0, Margin = new Thickness(0, 0, 4, 0), WidthRequest = 18, HeightRequest = 18, HorizontalOptions = LayoutOptions.End, VerticalOptions = LayoutOptions.Start }; // 外层椭圆(边框) var outerEllipse = new Ellipse { Stroke = Color.FromArgb(255, 99, 188, 205), // #63BBCD Fill = Colors.White, WidthRequest = 16, HeightRequest = 16, HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center }; // 选中填充椭圆(命名为check,用于状态切换) var checkEllipse = new Ellipse { Name = "check", Fill = Color.FromArgb(255, 99, 188, 205), // #63BBCD WidthRequest = 16, HeightRequest = 16, HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center, Opacity = 0 // 默认未选中透明 }; // 添加椭圆到图标Grid iconGrid.Children.Add(outerEllipse); iconGrid.Children.Add(checkEllipse); // 创建内容展示器 var contentPresenter = new ContentPresenter { GridColumn = 1 }; // 添加子控件到内部Grid innerGrid.Children.Add(iconGrid); innerGrid.Children.Add(contentPresenter); // 将内部Grid设为根Border的子控件 rootBorder.Content = innerGrid;
步骤2:添加视觉状态管理
对应原XAML中的VisualStateGroups,构建Checked/Unchecked状态切换逻辑:
// 创建视觉状态组列表 var visualStateGroupList = new VisualStateGroupList(); // 创建CheckedStates状态组 var checkedStateGroup = new VisualStateGroup { Name = "CheckedStates" }; // 构建Checked状态 var checkedState = new VisualState { Name = "Checked" }; checkedState.Setters.Add(new Setter { Property = Border.StrokeProperty, Value = Color.FromArgb(255, 255, 51, 0) }); // #FF3300 checkedState.Setters.Add(new Setter { TargetName = "check", Property = VisualElement.OpacityProperty, Value = 1 }); // 构建Unchecked状态 var uncheckedState = new VisualState { Name = "Unchecked" }; uncheckedState.Setters.Add(new Setter { Property = VisualElement.BackgroundColorProperty, Value = Colors.Transparent }); uncheckedState.Setters.Add(new Setter { Property = Border.StrokeProperty, Value = Color.FromArgb(255, 243, 242, 241) }); // #F3F2F1 uncheckedState.Setters.Add(new Setter { TargetName = "check", Property = VisualElement.OpacityProperty, Value = 0 }); // 将状态添加到状态组 checkedStateGroup.States.Add(checkedState); checkedStateGroup.States.Add(uncheckedState); // 将状态组添加到列表 visualStateGroupList.Add(checkedStateGroup); // 关联视觉状态到根Border VisualStateManager.SetVisualStateGroups(rootBorder, visualStateGroupList);
步骤3:创建ControlTemplate并应用到RadioButton
将构建好的视觉树和状态管理整合为ControlTemplate,然后通过Style或直接赋值给RadioButton:
// 创建ControlTemplate var radioButtonTemplate = new ControlTemplate(() => rootBorder); // 方式1:创建全局Style应用到所有RadioButton var radioButtonStyle = new Style(typeof(RadioButton)); radioButtonStyle.Setters.Add(new Setter { Property = RadioButton.ControlTemplateProperty, Value = radioButtonTemplate }); Application.Current.Resources.Add(typeof(RadioButton), radioButtonStyle); // 方式2:直接给单个RadioButton赋值 var customRadioButton = new RadioButton { ControlTemplate = radioButtonTemplate, Content = "自定义单选按钮" };
这样就能完全复现你原XAML模板的效果,所有属性、状态切换逻辑都和原模板一致。
内容的提问来源于stack exchange,提问作者vordonez
相关产品推荐
相关产品推荐

