Refactor RadioButton

use axaml theme
This commit is contained in:
CHINBOY
2025-06-10 13:29:27 +08:00
parent 482a4bbf4f
commit 8a7fc0dedd
5 changed files with 90 additions and 163 deletions
@@ -6,6 +6,7 @@
<atom:ControlThemesProvider.ControlThemes>
<ResourceInclude Source="Alert/Themes/AlertTheme.axaml" />
<ResourceInclude Source="CheckBox/Themes/CheckBoxTheme.axaml" />
<ResourceInclude Source="RadioButton/Themes/RadioButtonTheme.axaml" />
<ResourceInclude Source="Tag/Themes/TagTheme.axaml" />
<ResourceInclude Source="Pagination/Themes/PaginationThemes.axaml" />
<ResourceInclude Source="ScrollBar/Themes/ScrollBarThemes.axaml" />
@@ -81,7 +81,6 @@ namespace AtomUI.Theme
themes.Add(new AtomUI.Controls.PrimaryButtonTheme());
themes.Add(new AtomUI.Controls.PrimaryDropdownButtonTheme());
themes.Add(new AtomUI.Controls.ProgressBarTheme());
themes.Add(new AtomUI.Controls.RadioButtonTheme());
themes.Add(new AtomUI.Controls.RangeDatePickerFlyoutPresenterTheme());
themes.Add(new AtomUI.Controls.RangeDatePickerTheme());
themes.Add(new AtomUI.Controls.RangeTimePickerTheme());
@@ -1,162 +0,0 @@
using AtomUI.Theme;
using AtomUI.Theme.Styling;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Data;
using Avalonia.Data.Converters;
using Avalonia.Input;
using Avalonia.Layout;
using Avalonia.Styling;
namespace AtomUI.Controls;
[ControlThemeProvider]
internal class RadioButtonTheme : BaseControlTheme
{
internal const string FramePart = "PART_Frame";
internal const string IndicatorPart = "PART_Indicator";
internal const string LabelTextPart = "PART_LabelText";
public RadioButtonTheme()
: base(typeof(RadioButton))
{
}
protected override IControlTemplate BuildControlTemplate()
{
return new FuncControlTemplate<RadioButton>((radioButton, scope) =>
{
var frame = new Border
{
Name = FramePart,
Padding = new Thickness(0, 1, 0, 1)
};
CreateTemplateParentBinding(frame, Border.BackgroundProperty, RadioButton.BackgroundProperty);
CreateTemplateParentBinding(frame, Border.BorderBrushProperty, RadioButton.BorderBrushProperty);
CreateTemplateParentBinding(frame, Border.BorderThicknessProperty, RadioButton.BorderThicknessProperty);
CreateTemplateParentBinding(frame, Border.CornerRadiusProperty, RadioButton.CornerRadiusProperty);
var layout = new DockPanel
{
LastChildFill = true
};
var indicator = new RadioIndicator
{
Name = IndicatorPart,
VerticalAlignment = VerticalAlignment.Center
};
DockPanel.SetDock(indicator, Dock.Left);
CreateTemplateParentBinding(indicator, RadioIndicator.IsMotionEnabledProperty,
RadioButton.IsMotionEnabledProperty);
CreateTemplateParentBinding(indicator, RadioIndicator.IsWaveAnimationEnabledProperty,
RadioButton.IsWaveSpiritEnabledProperty);
CreateTemplateParentBinding(indicator, RadioIndicator.IsEnabledProperty, RadioButton.IsEnabledProperty);
CreateTemplateParentBinding(indicator, RadioIndicator.IsCheckedProperty, RadioButton.IsCheckedProperty);
layout.Children.Add(indicator);
var labelText = new TextBlock()
{
Name = LabelTextPart,
VerticalAlignment = VerticalAlignment.Center,
};
CreateTemplateParentBinding(labelText, TextBlock.TextProperty, RadioButton.ContentProperty,
BindingMode.Default,
new FuncValueConverter<object?, string?>(content => content?.ToString()));
CreateTemplateParentBinding(labelText, TextBlock.FontSizeProperty, RadioButton.FontSizeProperty);
CreateTemplateParentBinding(labelText, TextBlock.IsVisibleProperty, RadioButton.ContentProperty,
BindingMode.Default,
ObjectConverters.IsNotNull);
layout.Children.Add(labelText);
frame.Child = layout;
return frame;
});
}
protected override void BuildStyles()
{
var commonStyle = new Style(selector => selector.Nesting());
commonStyle.Add(RadioButton.CursorProperty,
new SetterValueFactory<Cursor>(() => new Cursor(StandardCursorType.Hand)));
commonStyle.Add(RadioButton.HorizontalAlignmentProperty, HorizontalAlignment.Left);
var disableStyle =
new Style(selector => selector.Nesting().PropertyEquals(InputElement.IsEnabledProperty, false));
disableStyle.Add(TemplatedControl.ForegroundProperty, SharedTokenKey.ColorTextDisabled);
commonStyle.Add(disableStyle);
var labelTextStyle = new Style(selector => selector.Nesting().Template().Name(LabelTextPart));
labelTextStyle.Add(ContentPresenter.MarginProperty, RadioButtonTokenKey.TextMargin);
commonStyle.Add(labelTextStyle);
Add(commonStyle);
BuildIndicatorStyle();
}
private void BuildIndicatorStyle()
{
{
var indicatorStyle = new Style(selector => selector.Nesting().Template().Name(IndicatorPart));
indicatorStyle.Add(RadioIndicator.RadioSizeProperty, RadioButtonTokenKey.RadioSize);
indicatorStyle.Add(RadioIndicator.WidthProperty, RadioButtonTokenKey.RadioSize);
indicatorStyle.Add(RadioIndicator.HeightProperty, RadioButtonTokenKey.RadioSize);
indicatorStyle.Add(RadioIndicator.DotSizeValueProperty, RadioButtonTokenKey.DotSize);
indicatorStyle.Add(RadioIndicator.DotPaddingProperty, RadioButtonTokenKey.DotPadding);
Add(indicatorStyle);
}
var disableStyle =
new Style(selector => selector.Nesting().PropertyEquals(InputElement.IsEnabledProperty, false));
{
var indicatorStyle = new Style(selector => selector.Nesting().Template().Name(IndicatorPart));
indicatorStyle.Add(RadioIndicator.RadioBackgroundProperty, SharedTokenKey.ColorBgContainerDisabled);
indicatorStyle.Add(RadioIndicator.RadioBorderBrushProperty, SharedTokenKey.ColorBorder);
indicatorStyle.Add(RadioIndicator.RadioInnerBackgroundProperty, RadioButtonTokenKey.DotColorDisabled);
disableStyle.Add(indicatorStyle);
}
Add(disableStyle);
var enabledStyle =
new Style(selector => selector.Nesting().PropertyEquals(InputElement.IsEnabledProperty, true));
{
{
var indicatorStyle = new Style(selector => selector.Nesting().Template().Name(IndicatorPart));
indicatorStyle.Add(RadioIndicator.RadioInnerBackgroundProperty, RadioButtonTokenKey.RadioColor);
indicatorStyle.Add(RadioIndicator.RadioBorderBrushProperty, SharedTokenKey.ColorBorder);
enabledStyle.Add(indicatorStyle);
}
var checkedStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.Checked));
{
var indicatorStyle = new Style(selector => selector.Nesting().Template().Name(IndicatorPart));
indicatorStyle.Add(RadioIndicator.RadioBorderBrushProperty, SharedTokenKey.ColorPrimary);
indicatorStyle.Add(RadioIndicator.RadioBackgroundProperty, SharedTokenKey.ColorPrimary);
checkedStyle.Add(indicatorStyle);
}
enabledStyle.Add(checkedStyle);
var unCheckedStyle =
new Style(selector => selector.Nesting().Not(x => x.Nesting().Class(StdPseudoClass.Checked)));
{
var indicatorStyle = new Style(selector => selector.Nesting().Template().Name(IndicatorPart));
indicatorStyle.Add(RadioIndicator.RadioBackgroundProperty, SharedTokenKey.ColorBgContainer);
unCheckedStyle.Add(indicatorStyle);
}
var unCheckedHoverStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.PointerOver));
{
var indicatorStyle = new Style(selector => selector.Nesting().Template().Name(IndicatorPart));
indicatorStyle.Add(RadioIndicator.RadioBorderBrushProperty, SharedTokenKey.ColorPrimary);
unCheckedHoverStyle.Add(indicatorStyle);
}
unCheckedStyle.Add(unCheckedHoverStyle);
enabledStyle.Add(unCheckedStyle);
}
Add(enabledStyle);
}
}
@@ -0,0 +1,8 @@
namespace AtomUI.Controls;
internal class RadioButtonThemeConstants
{
public const string FramePart = "PART_Frame";
public const string IndicatorPart = "PART_Indicator";
public const string LabelTextPart = "PART_LabelText";
}
@@ -4,6 +4,87 @@
xmlns:atom="https://atomui.net">
<ControlTheme x:Key="{x:Type atom:RadioButton}" TargetType="atom:RadioButton">
<Setter Property="Template">
<ControlTemplate>
<Border Name="{x:Static atom:RadioButtonThemeConstants.FramePart}"
Padding="0, 1, 0, 1"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<DockPanel LastChildFill="True">
<atom:RadioIndicator Name="{x:Static atom:RadioButtonThemeConstants.IndicatorPart}"
VerticalAlignment="Center"
DockPanel.Dock="Left"
IsMotionEnabled="{TemplateBinding IsMotionEnabled}"
IsWaveAnimationEnabled="{TemplateBinding IsWaveSpiritEnabled}"
IsEnabled="{TemplateBinding IsEnabled}"
IsChecked="{TemplateBinding IsChecked}" />
<atom:TextBlock Name="{x:Static atom:RadioButtonThemeConstants.LabelTextPart}"
VerticalAlignment="Center"
Text="{TemplateBinding Content}"
FontSize="{TemplateBinding FontSize}"
IsVisible="{TemplateBinding Content, Converter={x:Static ObjectConverters.IsNotNull}}" />
</DockPanel>
</Border>
</ControlTemplate>
</Setter>
<Setter Property="Cursor" Value="Hand" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="Foreground" Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorText}}" />
<Style Selector="^ /template/ atom|TextBlock#PART_LabelText">
<Setter Property="Margin" Value="{DynamicResource {x:Static atom:CheckBoxTokenKey.TextMargin}}" />
</Style>
<Style Selector="^:disabled">
<Setter Property="Foreground" Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorTextDisabled}}" />
</Style>
<!-- BuildIndicatorStyle 开始 -->
<Style Selector="^ /template/ atom|RadioIndicator#PART_Indicator">
<Setter Property="RadioSize" Value="{DynamicResource {x:Static atom:RadioButtonTokenKey.RadioSize}}" />
<Setter Property="Width" Value="{DynamicResource {x:Static atom:RadioButtonTokenKey.RadioSize}}" />
<Setter Property="Height" Value="{DynamicResource {x:Static atom:RadioButtonTokenKey.RadioSize}}" />
<Setter Property="DotSizeValue" Value="{DynamicResource {x:Static atom:RadioButtonTokenKey.DotSize}}" />
<Setter Property="DotPadding"
Value="{DynamicResource {x:Static atom:RadioButtonTokenKey.DotPadding}}" />
<Setter Property="RadioInnerBackground"
Value="{DynamicResource {x:Static atom:RadioButtonTokenKey.RadioColor}}" />
<Setter Property="RadioBorderBrush"
Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorBorder}}" />
</Style>
<Style Selector="^:checked">
<Style Selector="^ /template/ atom|RadioIndicator#PART_Indicator">
<Setter Property="RadioBorderBrush"
Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorPrimary}}" />
<Setter Property="RadioBackground"
Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorPrimary}}" />
</Style>
</Style>
<Style Selector="^:not(:checked)">
<Style Selector="^ /template/ atom|RadioIndicator#PART_Indicator">
<Setter Property="RadioBackground"
Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorBgContainer}}" />
</Style>
</Style>
<Style Selector="^:not(:checked):pointerover">
<Style Selector="^ /template/ atom|RadioIndicator#PART_Indicator">
<Setter Property="RadioBorderBrush"
Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorPrimary}}" />
</Style>
</Style>
<Style Selector="^:disabled">
<Style Selector="^ /template/ atom|RadioIndicator#PART_Indicator">
<Setter Property="RadioBackground"
Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorBgContainerDisabled}}" />
<Setter Property="RadioBorderBrush"
Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorBorder}}" />
<Setter Property="RadioInnerBackground"
Value="{DynamicResource {x:Static atom:RadioButtonTokenKey.DotColorDisabled}}" />
</Style>
</Style>
<!-- BuildIndicatorStyle 结束 -->
</ControlTheme>
</ResourceDictionary>