完成 BadgeRibbonCorner 重写

This commit is contained in:
polarboy
2024-07-22 12:31:33 +08:00
parent e4ef5a9b59
commit 8bc7e2c92f
8 changed files with 169 additions and 211 deletions
+2
View File
@@ -60,6 +60,7 @@ internal class BadgeToken : AbstractControlDesignToken
public Point BadgeRibbonOffset { get; set; }
public Transform? BadgeRibbonCornerTransform { get; set; }
public int BadgeRibbonCornerDarkenAmount { get; set; }
public Thickness BadgeRibbonTextPadding { get; set; }
#endregion
internal override void CalculateFromAlias()
@@ -88,5 +89,6 @@ internal class BadgeToken : AbstractControlDesignToken
BadgeRibbonCornerTransform = new ScaleTransform(1, 0.75);
BadgeRibbonCornerDarkenAmount = 15;
BadgeRibbonTextPadding = new Thickness(_globalToken.PaddingXS, 0);
}
}
+7 -4
View File
@@ -130,10 +130,12 @@ public partial class CountBadge : Control, IControlCustomStyle
public sealed override void ApplyTemplate()
{
base.ApplyTemplate();
CreateBadgeAdorner();
if (DecoratedTarget is null) {
CreateBadgeAdorner();
}
}
private void CreateBadgeAdorner()
private CountBadgeAdorner CreateBadgeAdorner()
{
if (_badgeAdorner is null) {
_badgeAdorner = new CountBadgeAdorner();
@@ -143,13 +145,14 @@ public partial class CountBadge : Control, IControlCustomStyle
SetupBadgeColor(BadgeColor);
}
}
return _badgeAdorner;
}
private void PrepareAdorner()
{
if (_adornerLayer is null && DecoratedTarget is not null) {
CreateBadgeAdorner();
var badgeAdorner = _badgeAdorner!;
var badgeAdorner = CreateBadgeAdorner();
_adornerLayer = AdornerLayer.GetAdornerLayer(this);
// 这里需要抛出异常吗?
if (_adornerLayer == null) {
+7 -4
View File
@@ -116,7 +116,7 @@ public partial class DotBadge : Control, IControlCustomStyle
PrepareAdorner();
}
private void CreateDotBadgeAdorner()
private DotBadgeAdorner CreateDotBadgeAdorner()
{
if (_dotBadgeAdorner is null) {
_dotBadgeAdorner = new DotBadgeAdorner();
@@ -126,13 +126,14 @@ public partial class DotBadge : Control, IControlCustomStyle
SetupDotColor(DotColor);
}
}
return _dotBadgeAdorner;
}
private void PrepareAdorner()
{
if (_adornerLayer is null && DecoratedTarget is not null) {
CreateDotBadgeAdorner();
var dotBadgeAdorner = _dotBadgeAdorner!;
var dotBadgeAdorner = CreateDotBadgeAdorner();
_adornerLayer = AdornerLayer.GetAdornerLayer(this);
// 这里需要抛出异常吗?
if (_adornerLayer == null) {
@@ -235,7 +236,9 @@ public partial class DotBadge : Control, IControlCustomStyle
public sealed override void ApplyTemplate()
{
base.ApplyTemplate();
CreateDotBadgeAdorner();
if (DecoratedTarget is null) {
CreateDotBadgeAdorner();
}
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs e)
@@ -1,5 +1,4 @@
using AtomUI.Styling;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Layout;
+28 -27
View File
@@ -88,33 +88,22 @@ public class RibbonBadge : Control, IControlCustomStyle
TextProperty);
AffectsRender<RibbonBadge>(RibbonColorProperty, PlacementProperty);
}
private bool _initialized = false;
private IControlCustomStyle _customStyle;
private RibbonBadgeAdorner? _ribbonBadgeAdorner;
private AdornerLayer? _adornerLayer;
void IControlCustomStyle.SetupUI()
{
_ribbonBadgeAdorner = new RibbonBadgeAdorner();
_customStyle.SetupTokenBindings();
HandleDecoratedTargetChanged();
if (RibbonColor is not null) {
SetupRibbonColor(RibbonColor);
}
}
private void HandleDecoratedTargetChanged()
{
if (_ribbonBadgeAdorner is not null) {
if (DecoratedTarget is null) {
VisualChildren.Add(_ribbonBadgeAdorner);
LogicalChildren.Add(_ribbonBadgeAdorner);
((ISetLogicalParent)_ribbonBadgeAdorner).SetParent(this);
_ribbonBadgeAdorner.IsAdornerMode = false;
} else if (DecoratedTarget is not null) {
_ribbonBadgeAdorner.IsAdornerMode = true;
VisualChildren.Add(DecoratedTarget);
LogicalChildren.Add(DecoratedTarget);
((ISetLogicalParent)DecoratedTarget).SetParent(this);
}
}
}
@@ -144,6 +133,14 @@ public class RibbonBadge : Control, IControlCustomStyle
}
}
public sealed override void ApplyTemplate()
{
base.ApplyTemplate();
if (DecoratedTarget is null) {
CreateBadgeAdorner();
}
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
@@ -159,7 +156,7 @@ public class RibbonBadge : Control, IControlCustomStyle
HideAdorner();
}
}
if (_initialized) {
if (VisualRoot is not null) {
if (e.Property == DecoratedTargetProperty) {
HandleDecoratedTargetChanged();
}
@@ -169,29 +166,33 @@ public class RibbonBadge : Control, IControlCustomStyle
}
}
}
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
private RibbonBadgeAdorner CreateBadgeAdorner()
{
base.OnAttachedToLogicalTree(e);
if (!_initialized) {
_customStyle.SetupUI();
_initialized = true;
if (_ribbonBadgeAdorner is null) {
_ribbonBadgeAdorner = new RibbonBadgeAdorner();
_customStyle.SetupTokenBindings();
HandleDecoratedTargetChanged();
if (RibbonColor is not null) {
SetupRibbonColor(RibbonColor);
}
}
return _ribbonBadgeAdorner;
}
private void PrepareAdorner()
{
if (_adornerLayer is null &&
DecoratedTarget is not null &&
_ribbonBadgeAdorner is not null) {
if (_adornerLayer is null && DecoratedTarget is not null) {
var ribbonBadgeAdorner = CreateBadgeAdorner();
_adornerLayer = AdornerLayer.GetAdornerLayer(this);
// 这里需要抛出异常吗?
if (_adornerLayer == null) {
return;
}
AdornerLayer.SetAdornedElement(_ribbonBadgeAdorner, this);
AdornerLayer.SetIsClipEnabled(_ribbonBadgeAdorner, false);
_adornerLayer.Children.Add(_ribbonBadgeAdorner);
AdornerLayer.SetAdornedElement(ribbonBadgeAdorner, this);
AdornerLayer.SetIsClipEnabled(ribbonBadgeAdorner, false);
_adornerLayer.Children.Add(ribbonBadgeAdorner);
}
}
+124 -123
View File
@@ -1,19 +1,16 @@
using System.Reactive.Linq;
using AtomUI.ColorSystem;
using AtomUI.ColorSystem;
using AtomUI.Controls.Utils;
using AtomUI.Data;
using AtomUI.Styling;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.Layout;
using Avalonia.LogicalTree;
using Avalonia.Media;
using Avalonia.Styling;
namespace AtomUI.Controls;
internal partial class RibbonBadgeAdorner : Control, IControlCustomStyle
internal class RibbonBadgeAdorner : Control, IControlCustomStyle
{
private bool _initialized = false;
private IControlCustomStyle _customStyle;
@@ -21,35 +18,50 @@ internal partial class RibbonBadgeAdorner : Control, IControlCustomStyle
private Geometry? _cornerGeometry;
private readonly BorderRenderHelper _borderRenderHelper;
public static readonly DirectProperty<RibbonBadgeAdorner, IBrush?> RibbonColorProperty =
AvaloniaProperty.RegisterDirect<RibbonBadgeAdorner, IBrush?>(
nameof(RibbonColor),
o => o.RibbonColor,
(o, v) => o.RibbonColor = v);
private IBrush? _ribbonColor;
public IBrush? RibbonColor
internal static readonly StyledProperty<IBrush?> RibbonColorProperty =
AvaloniaProperty.Register<RibbonBadgeAdorner, IBrush?>(
nameof(RibbonColor));
internal static readonly StyledProperty<string?> TextProperty =
AvaloniaProperty.Register<RibbonBadgeAdorner, string?>(
nameof(Text));
internal static readonly StyledProperty<RibbonBadgePlacement> PlacementProperty =
AvaloniaProperty.Register<RibbonBadgeAdorner, RibbonBadgePlacement>(
nameof(Placement));
internal static readonly StyledProperty<Point> OffsetProperty =
AvaloniaProperty.Register<RibbonBadgeAdorner, Point>(
nameof(Offset));
internal static readonly StyledProperty<CornerRadius> CornerRadiusProperty =
Border.CornerRadiusProperty.AddOwner<RibbonBadgeAdorner>();
internal static readonly StyledProperty<Point> BadgeRibbonOffsetProperty =
AvaloniaProperty.Register<RibbonBadgeAdorner, Point>(
nameof(BadgeRibbonOffset));
internal static readonly StyledProperty<int> BadgeRibbonCornerDarkenAmountProperty =
AvaloniaProperty.Register<RibbonBadgeAdorner, int>(
nameof(BadgeRibbonCornerDarkenAmount));
internal static readonly StyledProperty<Transform?> BadgeRibbonCornerTransformProperty =
AvaloniaProperty.Register<RibbonBadgeAdorner, Transform?>(
nameof(BadgeRibbonCornerTransform));
internal IBrush? RibbonColor
{
get => _ribbonColor;
set => SetAndRaise(RibbonColorProperty, ref _ribbonColor, value);
get => GetValue(RibbonColorProperty);
set => SetValue(RibbonColorProperty, value);
}
public static readonly DirectProperty<RibbonBadgeAdorner, string?> TextProperty =
AvaloniaProperty.RegisterDirect<RibbonBadgeAdorner, string?>(
nameof(Text),
o => o.Text,
(o, v) => o.Text = v);
private string? _text;
public string? Text
internal string? Text
{
get => _text;
set => SetAndRaise(TextProperty, ref _text, value);
get => GetValue(TextProperty);
set => SetValue(TextProperty, value);
}
public static readonly DirectProperty<RibbonBadgeAdorner, bool> IsAdornerModeProperty =
internal static readonly DirectProperty<RibbonBadgeAdorner, bool> IsAdornerModeProperty =
AvaloniaProperty.RegisterDirect<RibbonBadgeAdorner, bool>(
nameof(IsAdornerMode),
o => o.IsAdornerMode,
@@ -57,41 +69,48 @@ internal partial class RibbonBadgeAdorner : Control, IControlCustomStyle
private bool _isAdornerMode = false;
public bool IsAdornerMode
internal bool IsAdornerMode
{
get => _isAdornerMode;
set => SetAndRaise(IsAdornerModeProperty, ref _isAdornerMode, value);
}
public static readonly DirectProperty<RibbonBadgeAdorner, RibbonBadgePlacement> PlacementProperty =
AvaloniaProperty.RegisterDirect<RibbonBadgeAdorner, RibbonBadgePlacement>(
nameof(Placement),
o => o.Placement,
(o, v) => o.Placement = v);
private RibbonBadgePlacement _placement;
// 当前有效的颜色
public RibbonBadgePlacement Placement
internal RibbonBadgePlacement Placement
{
get => _placement;
set => SetAndRaise(PlacementProperty, ref _placement, value);
get => GetValue(PlacementProperty);
set => SetValue(PlacementProperty, value);
}
internal Point Offset
{
get => GetValue(OffsetProperty);
set => SetValue(OffsetProperty, value);
}
internal CornerRadius CornerRadius
{
get => GetValue(CornerRadiusProperty);
set => SetValue(CornerRadiusProperty, value);
}
internal Point BadgeRibbonOffset
{
get => GetValue(BadgeRibbonOffsetProperty);
set => SetValue(BadgeRibbonOffsetProperty, value);
}
public static readonly DirectProperty<RibbonBadgeAdorner, Point> OffsetProperty =
AvaloniaProperty.RegisterDirect<RibbonBadgeAdorner, Point>(
nameof(Offset),
o => o.Offset,
(o, v) => o.Offset = v);
private Point _offset;
public Point Offset
internal int BadgeRibbonCornerDarkenAmount
{
get => _offset;
set => SetAndRaise(OffsetProperty, ref _offset, value);
get => GetValue(BadgeRibbonCornerDarkenAmountProperty);
set => SetValue(BadgeRibbonCornerDarkenAmountProperty, value);
}
internal Transform? BadgeRibbonCornerTransform
{
get => GetValue(BadgeRibbonCornerTransformProperty);
set => SetValue(BadgeRibbonCornerTransformProperty, value);
}
static RibbonBadgeAdorner()
{
AffectsMeasure<RibbonBadgeAdorner>(TextProperty, IsAdornerModeProperty);
@@ -108,64 +127,46 @@ internal partial class RibbonBadgeAdorner : Control, IControlCustomStyle
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
{
base.OnAttachedToLogicalTree(e);
if (Styles.Count == 0) {
_customStyle.BuildStyles();
}
}
void IControlCustomStyle.BuildStyles()
{
var commonStyle = new Style(selector => selector.OfType<RibbonBadgeAdorner>());
commonStyle.Add(RibbonColorProperty, GlobalResourceKey.ColorPrimary);
commonStyle.Add(CornerRadiusProperty, GlobalResourceKey.BorderRadiusSM);
commonStyle.Add(BadgeRibbonOffsetProperty, BadgeResourceKey.BadgeRibbonOffset);
commonStyle.Add(BadgeRibbonCornerTransformProperty, BadgeResourceKey.BadgeRibbonCornerTransform);
commonStyle.Add(BadgeRibbonCornerDarkenAmountProperty, BadgeResourceKey.BadgeRibbonCornerDarkenAmount);
var labelStyle = new Style(selector => selector.Nesting().Child().OfType<TextBlock>());
labelStyle.Add(TextBlock.ForegroundProperty, GlobalResourceKey.ColorTextLightSolid);
labelStyle.Add(TextBlock.LineHeightProperty, BadgeResourceKey.BadgeFontHeight);
labelStyle.Add(TextBlock.PaddingProperty, BadgeResourceKey.BadgeRibbonTextPadding);
commonStyle.Add(labelStyle);
Styles.Add(commonStyle);
}
public sealed override void ApplyTemplate()
{
base.ApplyTemplate();
if (!_initialized) {
_customStyle.SetupUI();
HorizontalAlignment = HorizontalAlignment.Left;
VerticalAlignment = VerticalAlignment.Top;
_textBlock = new TextBlock()
{
Text = Text,
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Center,
};
((ISetLogicalParent)_textBlock).SetParent(this);
VisualChildren.Add(_textBlock);
BuildCornerGeometry();
_initialized = true;
}
}
void IControlCustomStyle.SetupUI()
{
HorizontalAlignment = HorizontalAlignment.Left;
VerticalAlignment = VerticalAlignment.Top;
_textBlock = new TextBlock()
{
Text = Text,
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Center,
};
LogicalChildren.Add(_textBlock);
VisualChildren.Add(_textBlock);
_customStyle.SetupTokenBindings();
BuildCornerGeometry();
}
void IControlCustomStyle.SetupTokenBindings()
{
BindUtils.CreateTokenBinding(this, BadgeRibbonOffsetTokenProperty, BadgeResourceKey.BadgeRibbonOffset);
BindUtils.CreateTokenBinding(this, MarginXSTokenProperty, GlobalResourceKey.MarginXS);
BindUtils.CreateTokenBinding(this, ColorPrimaryTokenProperty, GlobalResourceKey.ColorPrimary);
BindUtils.CreateTokenBinding(this, BadgeRibbonCornerTransformTokenProperty,
BadgeResourceKey.BadgeRibbonCornerTransform);
BindUtils.CreateTokenBinding(this, BadgeRibbonCornerDarkenAmountTokenProperty,
BadgeResourceKey.BadgeRibbonCornerDarkenAmount);
BindUtils.CreateTokenBinding(this, BorderRadiusSMTokenProperty, GlobalResourceKey.BorderRadiusSM);
if (_textBlock is not null) {
BindUtils.CreateTokenBinding(_textBlock, TextBlock.ForegroundProperty,
GlobalResourceKey.ColorTextLightSolid);
BindUtils.CreateTokenBinding(_textBlock, TextBlock.LineHeightProperty,
BadgeResourceKey.BadgeFontHeight);
BindUtils.CreateTokenBinding(_textBlock, TextBlock.PaddingProperty, GlobalResourceKey.PaddingXS,
BindingPriority.Template,
o =>
{
if (o is double value) {
return new Thickness(value, 0);
}
return o;
});
}
}
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
// TODO 这里是否需要增加一个什么判断?
_customStyle.SetupTokenBindings();
}
protected override Size MeasureOverride(Size availableSize)
{
var size = base.MeasureOverride(availableSize);
@@ -191,7 +192,7 @@ internal partial class RibbonBadgeAdorner : Control, IControlCustomStyle
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
if (_initialized) {
if (VisualRoot is not null) {
if (e.Property == PlacementProperty) {
BuildCornerGeometry(true);
}
@@ -200,7 +201,7 @@ internal partial class RibbonBadgeAdorner : Control, IControlCustomStyle
public override void Render(DrawingContext context)
{
var backgroundBrush = (SolidColorBrush)(RibbonColor ?? _colorPrimaryToken)!;
var backgroundBrush = RibbonColor as SolidColorBrush;
{
var textRect = GetTextRect();
using var state = context.PushTransform(Matrix.CreateTranslation(textRect.X, textRect.Y));
@@ -209,14 +210,14 @@ internal partial class RibbonBadgeAdorner : Control, IControlCustomStyle
borderThickness: new Thickness(0),
backgroundSizing: BackgroundSizing.OuterBorderEdge,
finalSize: textRect.Size,
cornerRadius: new CornerRadius(topLeft: _borderRadiusSMToken.TopLeft,
topRight: _borderRadiusSMToken.TopRight,
cornerRadius: new CornerRadius(topLeft: CornerRadius.TopLeft,
topRight: CornerRadius.TopRight,
bottomLeft: Placement == RibbonBadgePlacement.Start
? 0
: _borderRadiusSMToken.BottomLeft,
: CornerRadius.BottomLeft,
bottomRight: Placement == RibbonBadgePlacement.End
? 0
: _borderRadiusSMToken.BottomRight),
: CornerRadius.BottomRight),
background: backgroundBrush,
borderBrush: null,
boxShadows: new BoxShadows());
@@ -224,8 +225,8 @@ internal partial class RibbonBadgeAdorner : Control, IControlCustomStyle
{
var cornerRect = GetCornerRect();
using var state = context.PushTransform(Matrix.CreateTranslation(cornerRect.X, cornerRect.Y));
var backgroundColor = backgroundBrush.Color;
var cornerBrush = new SolidColorBrush(backgroundColor.Darken(_badgeRibbonCornerDarkenAmountToken));
var backgroundColor = backgroundBrush?.Color;
var cornerBrush = backgroundColor.HasValue ? new SolidColorBrush(backgroundColor.Value.Darken(BadgeRibbonCornerDarkenAmount)) : default;
context.DrawGeometry(cornerBrush, null, _cornerGeometry!);
}
}
@@ -239,11 +240,11 @@ internal partial class RibbonBadgeAdorner : Control, IControlCustomStyle
var offsetX = 0d;
var offsetY = 0d;
if (IsAdornerMode) {
offsetY += _badgeRibbonOffsetToken.Y;
offsetY += BadgeRibbonOffset.Y;
if (Placement == RibbonBadgePlacement.End) {
offsetX = DesiredSize.Width - _textBlock.DesiredSize.Width + _badgeRibbonOffsetToken.X;
offsetX = DesiredSize.Width - _textBlock.DesiredSize.Width + BadgeRibbonOffset.X;
} else {
offsetX = -_badgeRibbonOffsetToken.X;
offsetX = -BadgeRibbonOffset.X;
}
}
@@ -280,8 +281,8 @@ internal partial class RibbonBadgeAdorner : Control, IControlCustomStyle
private void BuildCornerGeometry(bool force = false)
{
if (force || _cornerGeometry is null) {
var width = _badgeRibbonOffsetToken.X;
var height = _badgeRibbonOffsetToken.Y;
var width = BadgeRibbonOffset.X;
var height = BadgeRibbonOffset.Y;
var geometryStream = new StreamGeometry();
using var context = geometryStream.Open();
var p1 = new Point(0, 0);
@@ -293,8 +294,8 @@ internal partial class RibbonBadgeAdorner : Control, IControlCustomStyle
context.EndFigure(true);
_cornerGeometry = geometryStream;
var transforms = new TransformGroup();
if (_badgeRibbonCornerTransformToken is not null) {
transforms.Children.Add(_badgeRibbonCornerTransformToken);
if (BadgeRibbonCornerTransform is not null) {
transforms.Children.Add(BadgeRibbonCornerTransform);
}
if (Placement == RibbonBadgePlacement.Start) {
@@ -1,52 +0,0 @@
using Avalonia;
using Avalonia.Media;
namespace AtomUI.Controls;
internal partial class RibbonBadgeAdorner
{
#region Control token 值绑定属性定义
private Point _badgeRibbonOffsetToken;
private static readonly DirectProperty<RibbonBadgeAdorner, Point> BadgeRibbonOffsetTokenProperty =
AvaloniaProperty.RegisterDirect<RibbonBadgeAdorner, Point>(
nameof(_badgeRibbonOffsetToken),
o => o._badgeRibbonOffsetToken,
(o, v) => o._badgeRibbonOffsetToken = v);
private double _marginXSToken;
private static readonly DirectProperty<RibbonBadgeAdorner, double> MarginXSTokenProperty =
AvaloniaProperty.RegisterDirect<RibbonBadgeAdorner, double>(
nameof(_marginXSToken),
o => o._marginXSToken,
(o, v) => o._marginXSToken = v);
private IBrush? _colorPrimaryToken;
private static readonly DirectProperty<RibbonBadgeAdorner, IBrush?> ColorPrimaryTokenProperty =
AvaloniaProperty.RegisterDirect<RibbonBadgeAdorner, IBrush?>(
nameof(_colorPrimaryToken),
o => o._colorPrimaryToken,
(o, v) => o._colorPrimaryToken = v);
private int _badgeRibbonCornerDarkenAmountToken;
private static readonly DirectProperty<RibbonBadgeAdorner, int> BadgeRibbonCornerDarkenAmountTokenProperty =
AvaloniaProperty.RegisterDirect<RibbonBadgeAdorner, int>(
nameof(_badgeRibbonCornerDarkenAmountToken),
o => o._badgeRibbonCornerDarkenAmountToken,
(o, v) => o._badgeRibbonCornerDarkenAmountToken = v);
private Transform? _badgeRibbonCornerTransformToken;
private static readonly DirectProperty<RibbonBadgeAdorner, Transform?> BadgeRibbonCornerTransformTokenProperty =
AvaloniaProperty.RegisterDirect<RibbonBadgeAdorner, Transform?>(
nameof(_badgeRibbonCornerTransformToken),
o => o._badgeRibbonCornerTransformToken,
(o, v) => o._badgeRibbonCornerTransformToken = v);
private CornerRadius _borderRadiusSMToken;
private static readonly DirectProperty<RibbonBadgeAdorner, CornerRadius> BorderRadiusSMTokenProperty =
AvaloniaProperty.RegisterDirect<RibbonBadgeAdorner, CornerRadius>(
nameof(_borderRadiusSMToken),
o => o._borderRadiusSMToken,
(o, v) => o._borderRadiusSMToken = v);
#endregion
}
@@ -40,6 +40,7 @@ namespace AtomUI.Styling
public static readonly TokenResourceKey BadgeRibbonOffset = new TokenResourceKey("Badge.BadgeRibbonOffset");
public static readonly TokenResourceKey BadgeRibbonCornerTransform = new TokenResourceKey("Badge.BadgeRibbonCornerTransform");
public static readonly TokenResourceKey BadgeRibbonCornerDarkenAmount = new TokenResourceKey("Badge.BadgeRibbonCornerDarkenAmount");
public static readonly TokenResourceKey BadgeRibbonTextPadding = new TokenResourceKey("Badge.BadgeRibbonTextPadding");
}
public static class ButtonResourceKey