Files
ShrlAlgoToolkit/AntDesignWPF/Controls/Avatar/Avatar.cs

257 lines
7.3 KiB
C#
Raw Normal View History

2025-07-31 20:12:24 +08:00
namespace AntDesignWPF.Controls;
2025-07-12 23:31:32 +08:00
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Windows.Media;
/// <summary>
/// Avatars can be used to represent people or objects. It supports images, Icons, or letters.
/// </summary>
[ContentProperty("Text")]
[TemplatePart(Name = "PART_Content", Type = typeof(ContentPresenter))]
public class Avatar : Control
2025-07-11 09:20:23 +08:00
{
2025-07-12 23:31:32 +08:00
#region Fields
private const string PART_Content = "PART_Content";
private ContentPresenter contentPresenter;
#endregion
#region Properties
public static readonly DependencyProperty IconProperty =
DependencyProperty.Register("Icon", typeof(string), typeof(Avatar), new PropertyMetadata(null, OnContentChanged));
2025-07-11 09:20:23 +08:00
/// <summary>
2025-07-12 23:31:32 +08:00
/// Gets/sets the icon type for an icon avatar.
2025-07-11 09:20:23 +08:00
/// </summary>
2025-07-12 23:31:32 +08:00
public string Icon
2025-07-11 09:20:23 +08:00
{
2025-07-12 23:31:32 +08:00
get { return (string)GetValue(IconProperty); }
set { SetValue(IconProperty, value); }
}
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as Avatar).SetContent(true);
}
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
public static readonly DependencyProperty ShapeProperty =
DependencyProperty.Register("Shape", typeof(Shapes), typeof(Avatar), new PropertyMetadata(Shapes.Circle));
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
/// <summary>
/// Gets/sets the shape of avatar.
/// </summary>
public Shapes Shape
{
get { return (Shapes)GetValue(ShapeProperty); }
set { SetValue(ShapeProperty, value); }
}
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
public static readonly DependencyProperty SizeProperty =
DependencyProperty.Register("Size", typeof(Sizes?), typeof(Avatar), new PropertyMetadata(null, OnSizeChanged));
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
/// <summary>
/// Gets/sets the size of the avatar.
/// </summary>
public Sizes? Size
{
get { return (Sizes?)GetValue(SizeProperty); }
set { SetValue(SizeProperty, value); }
}
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
private static void OnSizeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var avatar = d as Avatar;
var newValue = (Sizes?)e.NewValue;
var oldValue = (Sizes?)e.OldValue;
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
if (newValue.HasValue && newValue.Value >= 0)
2025-07-11 09:20:23 +08:00
{
2025-07-12 23:31:32 +08:00
var size = (double)newValue.Value;
avatar.SetValue(WidthProperty, size);
avatar.SetValue(HeightProperty, size);
avatar.SetValue(FontSizeProperty, size / 2);
2025-07-11 09:20:23 +08:00
}
2025-07-12 23:31:32 +08:00
else if (oldValue.HasValue && oldValue.Value >= 0)
2025-07-11 09:20:23 +08:00
{
2025-07-12 23:31:32 +08:00
avatar.ClearValue(WidthProperty);
avatar.ClearValue(HeightProperty);
avatar.ClearValue(FontSizeProperty);
2025-07-11 09:20:23 +08:00
}
2025-07-12 23:31:32 +08:00
}
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
public static readonly DependencyProperty SourceProperty =
DependencyProperty.Register("Source", typeof(ImageSource), typeof(Avatar), new PropertyMetadata(null, OnContentChanged));
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
/// <summary>
/// Gets/sets the ImageSource for an image avatar.
/// </summary>
public ImageSource Source
{
get { return (ImageSource)GetValue(SourceProperty); }
set { SetValue(SourceProperty, value); }
}
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(Avatar), new PropertyMetadata(string.Empty, OnContentChanged));
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
/// <summary>
/// Gets/sets the text for an text avatar.
/// </summary>
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
public static readonly DependencyProperty AlternativeProperty =
DependencyProperty.Register("Alternative", typeof(string), typeof(Avatar), new PropertyMetadata(string.Empty));
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
/// <summary>
/// Gets/sets the alternative text describing the image.
/// </summary>
public string Alternative
{
get { return (string)GetValue(AlternativeProperty); }
set { SetValue(AlternativeProperty, value); }
}
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
public static readonly DependencyProperty IsImageProperty =
DependencyProperty.Register("IsImage", typeof(bool), typeof(Avatar), new PropertyMetadata(false));
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
/// <summary>
/// Gets the current avatar type as an image.
/// </summary>
public bool IsImage
{
get { return (bool)GetValue(IsImageProperty); }
private set { SetValue(IsImageProperty, value); }
}
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
#endregion
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
#region Constructors
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
static Avatar()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(Avatar), new FrameworkPropertyMetadata(typeof(Avatar)));
}
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
#endregion
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
#region Overrides
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
contentPresenter = GetTemplateChild(PART_Content) as ContentPresenter;
SetContent(true);
}
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
#endregion
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
#region Private Methods
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
private void SetContent(bool imageExist)
{
if (contentPresenter == null) return;
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
var content = contentPresenter.Content;
// Clear Event
if (content is Image img)
{
ClearValue(IsImageProperty);
img.ImageFailed -= OnImageFailed;
2025-07-11 09:20:23 +08:00
}
2025-07-12 23:31:32 +08:00
else if (content is TextBlock block)
2025-07-11 09:20:23 +08:00
{
2025-07-12 23:31:32 +08:00
SizeChanged -= OnTextSizeChanged;
block.SizeChanged -= OnTextSizeChanged;
}
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
if (Source != null && imageExist)
{
if (content is not Image)
2025-07-11 09:20:23 +08:00
{
2025-07-12 23:31:32 +08:00
content = new Image();
2025-07-11 09:20:23 +08:00
}
2025-07-12 23:31:32 +08:00
SetCurrentValue(IsImageProperty, true);
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
var image = (Image)content;
image.Source = Source;
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
image.ImageFailed += OnImageFailed;
RenderOptions.SetBitmapScalingMode(image, BitmapScalingMode.HighQuality);
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
}
else if (Icon != null)
{
if (content is not Controls.Icon icon)
2025-07-11 09:20:23 +08:00
{
2025-07-12 23:31:32 +08:00
content = new Icon();
2025-07-11 09:20:23 +08:00
}
2025-07-12 23:31:32 +08:00
((Icon)content).Type = Icon;
}
else
{
var text = string.IsNullOrEmpty(Text) ? (imageExist ? string.Empty : Alternative) : Text;
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
if (content is not TextBlock)
{
content = new TextBlock();
}
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
var textblock = (TextBlock)content;
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
SizeChanged += OnTextSizeChanged;
textblock.SizeChanged += OnTextSizeChanged;
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
textblock.Text = text;
textblock.RenderTransformOrigin = new Point(0.5, 0.5);
2025-07-11 09:20:23 +08:00
}
2025-07-12 23:31:32 +08:00
// 引用传递对 Null 无效
contentPresenter.Content = content;
}
private void OnImageFailed(object sender, ExceptionRoutedEventArgs e)
{
SetContent(false);
}
2025-07-11 09:20:23 +08:00
2025-07-12 23:31:32 +08:00
/// <summary>
/// Autoset Font Size
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnTextSizeChanged(object sender, SizeChangedEventArgs e)
{
if (contentPresenter != null && contentPresenter.Content is TextBlock textBlock)
2025-07-11 09:20:23 +08:00
{
2025-07-12 23:31:32 +08:00
var childrenWidth = textBlock.ActualWidth;
var width = ActualWidth - 8;
var scale = 1d;
var left = 0d;
if (width < childrenWidth)
2025-07-11 09:20:23 +08:00
{
2025-07-12 23:31:32 +08:00
scale = width / childrenWidth;
left = ActualWidth / 2 - childrenWidth / 2;
2025-07-11 09:20:23 +08:00
}
2025-07-12 23:31:32 +08:00
textBlock.Margin = new Thickness(left, 0d, left, 0d);
textBlock.RenderTransform = new ScaleTransform(scale, scale);
}
2025-07-11 09:20:23 +08:00
}
2025-07-12 23:31:32 +08:00
#endregion
2025-07-11 09:20:23 +08:00
}