Refactor listbox themes

This commit is contained in:
CHINBOY
2025-06-15 23:44:35 +08:00
parent 6648c05ed8
commit 72ce5c366f
9 changed files with 140 additions and 270 deletions
@@ -19,6 +19,7 @@
<ResourceInclude Source="EmptyIndicator/Themes/EmptyIndicatorTheme.axaml" />
<ResourceInclude Source="Expander/Themes/ExpanderTheme.axaml" />
<ResourceInclude Source="GroupBox/Themes/GroupBoxTheme.axaml" />
<ResourceInclude Source="ListBox/Themes/ListBoxThemes.axaml" />
<ResourceInclude Source="RadioButton/Themes/RadioButtonTheme.axaml" />
<ResourceInclude Source="Pagination/Themes/PaginationThemes.axaml" />
<ResourceInclude Source="ScrollBar/Themes/ScrollBarThemes.axaml" />
@@ -20,8 +20,6 @@ namespace AtomUI.Theme
themes.Add(new AtomUI.Controls.HorizontalNavMenuTheme());
themes.Add(new AtomUI.Controls.HyperLinkTextBlockTheme());
themes.Add(new AtomUI.Controls.InlineNavMenuItemTheme());
themes.Add(new AtomUI.Controls.ListBoxItemTheme());
themes.Add(new AtomUI.Controls.ListBoxTheme());
themes.Add(new AtomUI.Controls.LoadingIndicatorAdornerTheme());
themes.Add(new AtomUI.Controls.LoadingIndicatorTheme());
themes.Add(new AtomUI.Controls.MenuFlyoutPresenterTheme());
@@ -1,134 +0,0 @@
using AtomUI.Theme;
using AtomUI.Theme.Styling;
using Avalonia.Controls;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Data;
using Avalonia.Data.Converters;
using Avalonia.Layout;
using Avalonia.Styling;
namespace AtomUI.Controls;
[ControlThemeProvider]
internal class ListBoxItemTheme : BaseControlTheme
{
public const string ContentPresenterPart = "PART_ContentPresenter";
public ListBoxItemTheme() : this(typeof(ListBoxItem))
{
}
protected ListBoxItemTheme(Type targetType) : base(targetType)
{
}
protected override IControlTemplate BuildControlTemplate()
{
return new FuncControlTemplate<ListBoxItem>((listBoxItem, scope) =>
{
var contentPresenter = new ContentPresenter
{
Name = ContentPresenterPart
};
CreateTemplateParentBinding(contentPresenter, ContentPresenter.ForegroundProperty,
TemplatedControl.ForegroundProperty);
CreateTemplateParentBinding(contentPresenter, ContentPresenter.BackgroundProperty,
TemplatedControl.BackgroundProperty);
CreateTemplateParentBinding(contentPresenter, ContentPresenter.CornerRadiusProperty,
TemplatedControl.CornerRadiusProperty);
CreateTemplateParentBinding(contentPresenter, ContentPresenter.ContentProperty,
ContentControl.ContentProperty,
BindingMode.Default,
new FuncValueConverter<object?, object?>(
o =>
{
if (o is string str)
{
return new TextBlock()
{
Text = str,
VerticalAlignment = VerticalAlignment.Center
};
}
return o;
}));
CreateTemplateParentBinding(contentPresenter, ContentPresenter.ContentTemplateProperty,
ContentControl.ContentTemplateProperty);
CreateTemplateParentBinding(contentPresenter, Layoutable.MinHeightProperty, Layoutable.MinHeightProperty);
CreateTemplateParentBinding(contentPresenter, ContentPresenter.PaddingProperty,
TemplatedControl.PaddingProperty);
CreateTemplateParentBinding(contentPresenter, ContentPresenter.HorizontalContentAlignmentProperty,
ContentControl.HorizontalContentAlignmentProperty);
CreateTemplateParentBinding(contentPresenter, ContentPresenter.VerticalContentAlignmentProperty,
ContentControl.VerticalContentAlignmentProperty);
return contentPresenter;
});
}
protected override void BuildStyles()
{
BuildCommonStyle();
BuildSizeTypeStyle();
BuildDisabledStyle();
}
private void BuildCommonStyle()
{
var commonStyle = new Style(selector => selector.Nesting());
commonStyle.Add(ListBoxItem.MarginProperty, ListBoxTokenKey.ItemMargin);
commonStyle.Add(ListBoxItem.ForegroundProperty, ListBoxTokenKey.ItemColor);
commonStyle.Add(ListBoxItem.BackgroundProperty, ListBoxTokenKey.ItemBgColor);
var disabledItemHoverStyle = new Style(selector =>
selector.Nesting().PropertyEquals(ListBoxItem.DisabledItemHoverEffectProperty, false).Class(StdPseudoClass.PointerOver));
disabledItemHoverStyle.Add(ListBoxItem.ForegroundProperty, ListBoxTokenKey.ItemHoverColor);
disabledItemHoverStyle.Add(ListBoxItem.BackgroundProperty, ListBoxTokenKey.ItemHoverBgColor);
commonStyle.Add(disabledItemHoverStyle);
var selectedStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.Selected));
selectedStyle.Add(ListBoxItem.ForegroundProperty, ListBoxTokenKey.ItemSelectedColor);
selectedStyle.Add(ListBoxItem.BackgroundProperty, ListBoxTokenKey.ItemSelectedBgColor);
commonStyle.Add(selectedStyle);
Add(commonStyle);
}
private void BuildSizeTypeStyle()
{
var largeStyle = new Style(selector =>
selector.Nesting().PropertyEquals(ListBoxItem.SizeTypeProperty, SizeType.Large));
largeStyle.Add(TemplatedControl.CornerRadiusProperty, SharedTokenKey.BorderRadius);
largeStyle.Add(Layoutable.MinHeightProperty, SharedTokenKey.ControlHeightLG);
largeStyle.Add(TemplatedControl.PaddingProperty, ListBoxTokenKey.ItemPaddingLG);
Add(largeStyle);
var middleStyle = new Style(selector =>
selector.Nesting().PropertyEquals(ListBoxItem.SizeTypeProperty, SizeType.Middle));
middleStyle.Add(TemplatedControl.CornerRadiusProperty, SharedTokenKey.BorderRadiusSM);
middleStyle.Add(Layoutable.MinHeightProperty, SharedTokenKey.ControlHeight);
middleStyle.Add(TemplatedControl.PaddingProperty, ListBoxTokenKey.ItemPadding);
Add(middleStyle);
var smallStyle = new Style(selector =>
selector.Nesting().PropertyEquals(ListBoxItem.SizeTypeProperty, SizeType.Small));
smallStyle.Add(TemplatedControl.CornerRadiusProperty, SharedTokenKey.BorderRadiusXS);
smallStyle.Add(Layoutable.MinHeightProperty, SharedTokenKey.ControlHeightSM);
smallStyle.Add(TemplatedControl.PaddingProperty, ListBoxTokenKey.ItemPaddingSM);
Add(smallStyle);
}
private void BuildDisabledStyle()
{
var disabledStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.Disabled));
var contentPresenterStyle = new Style(selector => selector.Nesting().Template().Name(ContentPresenterPart));
contentPresenterStyle.Add(ContentPresenter.ForegroundProperty, SharedTokenKey.ColorTextDisabled);
disabledStyle.Add(contentPresenterStyle);
Add(disabledStyle);
}
}
-121
View File
@@ -1,121 +0,0 @@
using AtomUI.Theme;
using AtomUI.Theme.Styling;
using Avalonia.Controls;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Styling;
namespace AtomUI.Controls;
[ControlThemeProvider]
internal class ListBoxTheme : BaseControlTheme
{
public const string FramePart = "PART_Frame";
public const string ScrollViewerPart = "PART_ScrollViewer";
public const string ItemsPresenterPart = "PART_ItemsPresenter";
public ListBoxTheme() : this(typeof(ListBox))
{
}
protected ListBoxTheme(Type targetType) : base(targetType)
{
}
protected override IControlTemplate BuildControlTemplate()
{
return new FuncControlTemplate<ListBox>((listBox, scope) =>
{
var frameBorder = new Border
{
Name = FramePart
};
CreateTemplateParentBinding(frameBorder, Border.BackgroundProperty, TemplatedControl.BackgroundProperty);
CreateTemplateParentBinding(frameBorder, Border.BorderBrushProperty, TemplatedControl.BorderBrushProperty);
CreateTemplateParentBinding(frameBorder, Border.BorderThicknessProperty, TemplatedControl.BorderThicknessProperty);
CreateTemplateParentBinding(frameBorder, Border.CornerRadiusProperty, TemplatedControl.CornerRadiusProperty);
var itemsPresenter = BuildItemsPresenter(listBox, scope);
var scrollViewer = BuildScrollViewer();
scrollViewer.Content = itemsPresenter;
frameBorder.Child = scrollViewer;
return frameBorder;
});
}
private ScrollViewer BuildScrollViewer()
{
var scrollViewer = new ScrollViewer
{
Name = ScrollViewerPart
};
CreateTemplateParentBinding(scrollViewer, ScrollViewer.AllowAutoHideProperty, ScrollViewer.AllowAutoHideProperty);
CreateTemplateParentBinding(scrollViewer, ScrollViewer.HorizontalScrollBarVisibilityProperty, ScrollViewer.HorizontalScrollBarVisibilityProperty);
CreateTemplateParentBinding(scrollViewer, ScrollViewer.VerticalScrollBarVisibilityProperty, ScrollViewer.VerticalScrollBarVisibilityProperty);
CreateTemplateParentBinding(scrollViewer, ScrollViewer.IsScrollChainingEnabledProperty, ScrollViewer.IsScrollChainingEnabledProperty);
CreateTemplateParentBinding(scrollViewer, ScrollViewer.IsDeferredScrollingEnabledProperty, ScrollViewer.IsDeferredScrollingEnabledProperty);
CreateTemplateParentBinding(scrollViewer, ScrollViewer.IsScrollInertiaEnabledProperty, ScrollViewer.IsScrollInertiaEnabledProperty);
return scrollViewer;
}
private ItemsPresenter BuildItemsPresenter(ListBox listBox, INameScope scope)
{
var itemsPresenter = new ItemsPresenter
{
Name = ItemsPresenterPart
};
itemsPresenter.RegisterInNameScope(scope);
CreateTemplateParentBinding(itemsPresenter, ItemsPresenter.ItemsPanelProperty, ItemsControl.ItemsPanelProperty);
return itemsPresenter;
}
protected override void BuildStyles()
{
BuildFixedStyle();
BuildCommonStyle();
BuildSizeTypeStyle();
}
private void BuildSizeTypeStyle()
{
var largeStyle =
new Style(selector => selector.Nesting().PropertyEquals(ListBox.SizeTypeProperty, SizeType.Large));
largeStyle.Add(Border.CornerRadiusProperty, SharedTokenKey.BorderRadiusLG);
Add(largeStyle);
var middleStyle =
new Style(selector => selector.Nesting().PropertyEquals(ListBox.SizeTypeProperty, SizeType.Middle));
middleStyle.Add(Border.CornerRadiusProperty, SharedTokenKey.BorderRadius);
Add(middleStyle);
var smallStyle =
new Style(selector => selector.Nesting().PropertyEquals(ListBox.SizeTypeProperty, SizeType.Small));
smallStyle.Add(Border.CornerRadiusProperty, SharedTokenKey.BorderRadiusSM);
Add(smallStyle);
}
private void BuildFixedStyle()
{
this.Add(ScrollViewer.HorizontalScrollBarVisibilityProperty, ScrollBarVisibility.Disabled);
this.Add(ScrollViewer.VerticalScrollBarVisibilityProperty, ScrollBarVisibility.Auto);
this.Add(ScrollViewer.IsScrollChainingEnabledProperty, true);
}
private void BuildCommonStyle()
{
var commonStyle = new Style(selector => selector.Nesting());
commonStyle.Add(Border.BorderBrushProperty, SharedTokenKey.ColorBorder);
var frameStyle = new Style(selector => selector.Nesting().Template().Name(FramePart));
frameStyle.Add(Decorator.PaddingProperty, ListBoxTokenKey.ContentPadding);
frameStyle.Add(Border.BackgroundProperty, SharedTokenKey.ColorBgContainer);
commonStyle.Add(frameStyle);
Add(commonStyle);
}
}
@@ -0,0 +1,62 @@
<ResourceDictionary
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:atom="https://atomui.net">
<atom:StringToTextBlockConverter x:Key="StringToTextBlockConverter"/>
<ControlTheme x:Key="{x:Type atom:ListBoxItem}" TargetType="atom:ListBoxItem">
<Setter Property="Template">
<ControlTemplate>
<ContentPresenter Name="{x:Static atom:ListBoxItemThemeConstants.ContentPresenterPart}"
Foreground="{TemplateBinding Foreground}"
Background="{TemplateBinding Background}"
CornerRadius="{TemplateBinding CornerRadius}"
Content="{TemplateBinding Content, Converter={StaticResource StringToTextBlockConverter}}"
ContentTemplate="{TemplateBinding ContentTemplate}"
MinHeight="{TemplateBinding MinHeight}"
Padding="{TemplateBinding Padding}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
/>
</ControlTemplate>
</Setter>
<Setter Property="Margin" Value="{DynamicResource {x:Static atom:ListBoxTokenKey.ItemMargin}}" />
<Setter Property="Foreground" Value="{DynamicResource {x:Static atom:ListBoxTokenKey.ItemColor}}" />
<Setter Property="Background" Value="{DynamicResource {x:Static atom:ListBoxTokenKey.ItemBgColor}}" />
<Style Selector="^:selected">
<Setter Property="Foreground" Value="{DynamicResource {x:Static atom:ListBoxTokenKey.ItemSelectedColor}}" />
<Setter Property="Background" Value="{DynamicResource {x:Static atom:ListBoxTokenKey.ItemSelectedBgColor}}" />
</Style>
<Style Selector="^[DisabledItemHoverEffect=False]:pointerover">
<Setter Property="Foreground" Value="{DynamicResource {x:Static atom:ListBoxTokenKey.ItemHoverColor}}" />
<Setter Property="Background" Value="{DynamicResource {x:Static atom:ListBoxTokenKey.ItemHoverBgColor}}" />
</Style>
<Style Selector="^[SizeType=Large]">
<Setter Property="CornerRadius" Value="{DynamicResource {x:Static atom:SharedTokenKey.BorderRadius}}" />
<Setter Property="MinHeight" Value="{DynamicResource {x:Static atom:SharedTokenKey.ControlHeightLG}}" />
<Setter Property="Padding" Value="{DynamicResource {x:Static atom:ListBoxTokenKey.ItemPaddingLG}}" />
</Style>
<Style Selector="^[SizeType=Middle]">
<Setter Property="CornerRadius" Value="{DynamicResource {x:Static atom:SharedTokenKey.BorderRadiusSM}}" />
<Setter Property="MinHeight" Value="{DynamicResource {x:Static atom:SharedTokenKey.ControlHeight}}" />
<Setter Property="Padding" Value="{DynamicResource {x:Static atom:ListBoxTokenKey.ItemPadding}}" />
</Style>
<Style Selector="^[SizeType=Small]">
<Setter Property="CornerRadius" Value="{DynamicResource {x:Static atom:SharedTokenKey.BorderRadiusXS}}" />
<Setter Property="MinHeight" Value="{DynamicResource {x:Static atom:SharedTokenKey.ControlHeightSM}}" />
<Setter Property="Padding" Value="{DynamicResource {x:Static atom:ListBoxTokenKey.ItemPaddingSM}}" />
</Style>
<Style Selector="^:disabled">
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorTextDisabled}}" />
</Style>
</Style>
</ControlTheme>
</ResourceDictionary>
@@ -0,0 +1,50 @@
<ResourceDictionary
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:atom="https://atomui.net">
<ControlTheme x:Key="{x:Type atom:ListBox}" TargetType="atom:ListBox">
<Setter Property="Template">
<ControlTemplate>
<Border Name="{x:Static atom:ListBoxThemeConstants.FramePart}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<ScrollViewer Name="{x:Static atom:ListBoxThemeConstants.ScrollViewerPart}"
AllowAutoHide="{TemplateBinding ScrollViewer.AllowAutoHide}"
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
IsScrollChainingEnabled="{TemplateBinding ScrollViewer.IsScrollChainingEnabled}"
IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
IsScrollInertiaEnabled="{TemplateBinding ScrollViewer.IsScrollInertiaEnabled}">
<ItemsPresenter Name="{x:Static atom:ListBoxThemeConstants.ItemsPresenterPart}"
ItemsPanel="{TemplateBinding ItemsPanel}" />
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
<Setter Property="ScrollViewer.IsScrollChainingEnabled" Value="True" />
<Setter Property="BorderBrush" Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorBorder}}" />
<Style Selector="^ /template/ Border#PART_Frame">
<Setter Property="Padding" Value="{DynamicResource {x:Static atom:ListBoxTokenKey.ContentPadding}}" />
<Setter Property="Background" Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorBgContainer}}" />
</Style>
<Style Selector="^[SizeType=Large]">
<Setter Property="CornerRadius" Value="{DynamicResource {x:Static atom:SharedTokenKey.BorderRadiusLG}}" />
</Style>
<Style Selector="^[SizeType=Middle]">
<Setter Property="CornerRadius" Value="{DynamicResource {x:Static atom:SharedTokenKey.BorderRadius}}" />
</Style>
<Style Selector="^[SizeType=Small]">
<Setter Property="CornerRadius" Value="{DynamicResource {x:Static atom:SharedTokenKey.BorderRadiusSM}}" />
</Style>
</ControlTheme>
</ResourceDictionary>
@@ -0,0 +1,13 @@
namespace AtomUI.Controls.Themes;
internal static class ListBoxThemeConstants
{
public const string FramePart = "PART_Frame";
public const string ScrollViewerPart = "PART_ScrollViewer";
public const string ItemsPresenterPart = "PART_ItemsPresenter";
}
internal static class ListBoxItemThemeConstants
{
public const string ContentPresenterPart = "PART_ContentPresenter";
}
@@ -0,0 +1,7 @@
<ResourceDictionary xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceInclude Source="ListBoxItemTheme.axaml" />
<ResourceInclude Source="ListBoxTheme.axaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
+7 -13
View File
@@ -6,7 +6,6 @@ using AtomUI.Theme.Utils;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.LogicalTree;
using Avalonia.Media;
namespace AtomUI.Controls;
@@ -51,23 +50,18 @@ public class MenuSeparator : AvaloniaSeparator,
context.DrawLine(linePen, new Point(0, offsetY), new Point(Bounds.Right, offsetY));
}
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
{
base.OnAttachedToLogicalTree(e);
_resourceBindingsDisposable = new CompositeDisposable();
}
protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
{
base.OnDetachedFromLogicalTree(e);
this.DisposeTokenBindings();
}
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
_resourceBindingsDisposable = new CompositeDisposable();
this.AddResourceBindingDisposable(TokenResourceBinder.CreateTokenBinding(this, LineWidthProperty, SharedTokenKey.LineWidth,
BindingPriority.Template,
new RenderScaleAwareDoubleConfigure(this)));
}
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnDetachedFromVisualTree(e);
this.DisposeTokenBindings();
}
}