using Melskin.Assets; namespace Melskin.Controls; /// /// 图标控件:支持 MaterialSymbol / Glyph / ImageSource / Geometry / Drawing / DrawingBrush。 /// 使用 DataTemplate 按需创建视觉树,属性变化即时切换模板。 /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// public class IconElement : Control { static IconElement() { DefaultStyleKeyProperty.OverrideMetadata(typeof(IconElement), new FrameworkPropertyMetadata(typeof(IconElement))); } /// /// 用于显示图标的控件。可以通过设置属性来指定图标的具体样式和内容。 /// public IconElement() { } #region 枚举 /// /// 用于定义图标内容类型的枚举。此枚举支持多种类型的内容,包括自动检测、Material 符号、字形、图像、几何图形、绘图以及画刷。 /// public enum IconContentType { /// /// 表示图标内容类型将自动检测。当设置此枚举值时,系统会根据提供的内容自动选择最合适的图标渲染方式。 /// Auto, /// /// 表示图标内容为Material符号类型。当设置此枚举值时,表示图标将使用Material设计风格的符号来渲染。 /// Material, /// /// 表示图标内容为字形类型。当设置此枚举值时,表示图标将使用字形数据来渲染。 /// Glyph, /// /// 表示图标内容为图像类型。当设置此枚举值时,表示图标将使用图像数据来渲染。 /// Image, /// /// 表示图标内容类型为几何图形。当ContentType设置为此值时,IconElement将使用指定的几何图形来渲染图标。 /// Geometry, /// /// 表示图标内容为绘图类型。当设置此枚举值时,表示图标将使用绘图数据来渲染。 /// Drawing, /// /// 表示图标内容类型为画刷。当ContentType设置为此值时,IconElement将使用指定的画刷来渲染图标。 /// Brush } #endregion #region 依赖属性 /// /// 用于获取或设置图标元素的符号。此属性定义了IconElement将显示的具体MaterialSymbol。 /// public static readonly DependencyProperty SymbolProperty = DependencyProperty.Register( nameof(Symbol), typeof(MaterialSymbol), typeof(IconElement), new PropertyMetadata(MaterialSymbol.CR, OnContentChanged)); /// /// 获取或设置图标元素的符号。此属性指定了IconElement将要展示的具体MaterialSymbol。 /// public MaterialSymbol Symbol { get => (MaterialSymbol)GetValue(SymbolProperty); set => SetValue(SymbolProperty, value); } /// /// 用于获取或设置图标的字形。此属性定义了IconElement将显示的具体字形字符串。 /// public static readonly DependencyProperty GlyphProperty = DependencyProperty.Register( nameof(Glyph), typeof(string), typeof(IconElement), new PropertyMetadata(string.Empty, OnContentChanged)); /// /// 获取或设置图标元素的字形代码。此属性定义了IconElement将显示的具体字形,通常用于指定字体图标。 /// public string? Glyph { get => (string)GetValue(GlyphProperty); set => SetValue(GlyphProperty, value); } /// /// 用于获取或设置图像源。此属性定义了IconElement将显示的具体图像。 /// public static readonly DependencyProperty ImageSourceProperty = DependencyProperty.Register( nameof(ImageSource), typeof(ImageSource), typeof(IconElement), new PropertyMetadata(null, OnContentChanged)); /// /// 用于获取或设置图标元素的图像源。此属性允许为IconElement指定一个图像,该图像将作为控件的内容显示。 /// public ImageSource? ImageSource { get => (ImageSource?)GetValue(ImageSourceProperty); set => SetValue(ImageSourceProperty, value); } /// /// 用于获取或设置图标元素的几何图形。此属性允许为IconElement指定一个自定义的Geometry对象,以显示特定形状或路径。 /// public static readonly DependencyProperty GeometryProperty = DependencyProperty.Register( nameof(Geometry), typeof(Geometry), typeof(IconElement), new PropertyMetadata(null, OnContentChanged)); /// /// 用于获取或设置图标元素的几何图形。此属性允许定义一个Geometry对象,该对象将被用来渲染IconElement中的形状。 /// public Geometry? Geometry { get => (Geometry?)GetValue(GeometryProperty); set => SetValue(GeometryProperty, value); } /// /// 用于获取或设置图标元素的绘图。此属性定义了IconElement将显示的具体绘图内容。 /// public static readonly DependencyProperty DrawingProperty = DependencyProperty.Register( nameof(Drawing), typeof(Drawing), typeof(IconElement), new PropertyMetadata(null, OnContentChanged)); /// /// 用于获取或设置图标元素的绘图。此属性允许您指定一个Drawing对象,该对象将作为图标的内容进行显示。 /// public Drawing? Drawing { get => (Drawing?)GetValue(DrawingProperty); set => SetValue(DrawingProperty, value); } /// /// 用于获取或设置图标元素的绘图刷。此属性定义了IconElement将使用的DrawingBrush,以控制图标显示时的填充样式。 /// public static readonly DependencyProperty DrawingBrushProperty = DependencyProperty.Register( nameof(DrawingBrush), typeof(DrawingBrush), typeof(IconElement), new PropertyMetadata(null, OnContentChanged)); /// /// /// public DrawingBrush? DrawingBrush { get => (DrawingBrush?)GetValue(DrawingBrushProperty); set => SetValue(DrawingBrushProperty, value); } /// /// 用于获取或设置图像的拉伸模式。此属性决定了IconElement中的图像如何被拉伸以填充可用空间。 /// public static readonly DependencyProperty ImageStretchProperty = DependencyProperty.Register( nameof(ImageStretch), typeof(Stretch), typeof(IconElement), new PropertyMetadata(Stretch.Uniform)); /// /// 用于获取或设置图像的拉伸模式。此属性定义了图标元素中图像如何适应其布局区域。 /// public Stretch ImageStretch { get => (Stretch)GetValue(ImageStretchProperty); set => SetValue(ImageStretchProperty, value); } /// /// 用于获取或设置几何图形的填充颜色。此属性定义了应用于几何图形内部的颜色刷。 /// public static readonly DependencyProperty GeometryFillProperty = DependencyProperty.Register( nameof(GeometryFill), typeof(Brush), typeof(IconElement), new PropertyMetadata(Brushes.Black)); /// /// 用于获取或设置几何图形填充的颜色或图案。此属性定义了IconElement中几何图形的填充样式。 /// public Brush GeometryFill { get => (Brush)GetValue(GeometryFillProperty); set => SetValue(GeometryFillProperty, value); } /// /// 用于获取或设置几何图形描边的画刷。此属性定义了应用于几何图形描边的颜色和样式。 /// public static readonly DependencyProperty GeometryStrokeProperty = DependencyProperty.Register( nameof(GeometryStroke), typeof(Brush), typeof(IconElement), new PropertyMetadata(null)); /// /// 用于获取或设置几何图形的描边画刷。此属性定义了IconElement中几何图形的描边样式。 /// public Brush? GeometryStroke { get => (Brush?)GetValue(GeometryStrokeProperty); set => SetValue(GeometryStrokeProperty, value); } /// /// /// public static readonly DependencyProperty GeometryStrokeThicknessProperty = DependencyProperty.Register( nameof(GeometryStrokeThickness), typeof(double), typeof(IconElement), new PropertyMetadata(1d)); /// /// /// public double GeometryStrokeThickness { get => (double)GetValue(GeometryStrokeThicknessProperty); set => SetValue(GeometryStrokeThicknessProperty, value); } /// /// 用于获取或设置图标元素的内容类型。此属性定义了IconElement将使用哪种类型的资源来显示内容,例如Material符号、Glyph字符、图像等。 /// public static readonly DependencyProperty ContentTypeProperty = DependencyProperty.Register( nameof(ContentType), typeof(IconContentType), typeof(IconElement), new PropertyMetadata(IconContentType.Auto, OnContentChanged)); /// /// 用于获取或设置图标元素的内容类型。此属性定义了IconElement将使用的具体内容类型,如Material、Glyph、Image等。 /// public IconContentType ContentType { get => (IconContentType)GetValue(ContentTypeProperty); set => SetValue(ContentTypeProperty, value); } private static readonly DependencyPropertyKey EffectiveContentTypePropertyKey = DependencyProperty.RegisterReadOnly( nameof(EffectiveContentType), typeof(IconContentType), typeof(IconElement), new PropertyMetadata(IconContentType.Material)); /// /// 获取当前图标元素实际使用的内容类型。此属性反映了IconElement根据设置的Symbol、Glyph、ImageSource等属性自动确定并使用的具体内容类型。 /// public static readonly DependencyProperty EffectiveContentTypeProperty = EffectiveContentTypePropertyKey.DependencyProperty; /// /// 获取当前图标元素实际使用的内容类型。此属性根据设置的符号、字形等自动确定最合适的IconContentType。 /// public IconContentType EffectiveContentType => (IconContentType)GetValue(EffectiveContentTypeProperty); private static readonly DependencyPropertyKey DrawingImagePropertyKey = DependencyProperty.RegisterReadOnly( nameof(DrawingImage), typeof(ImageSource), typeof(IconElement), new PropertyMetadata(null)); /// /// 用于获取绘制图像的只读属性。此属性表示从Drawing生成的ImageSource。 /// public static readonly DependencyProperty DrawingImageProperty = DrawingImagePropertyKey.DependencyProperty; /// /// 用于获取表示当前绘制内容的ImageSource。此属性是只读的,其值基于Drawing属性自动生成。 /// public ImageSource? DrawingImage => (ImageSource?)GetValue(DrawingImageProperty); #endregion #region 内容变更逻辑 private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var ctl = (IconElement)d; ctl.UpdateDerived(); ctl.UpdateEffective(); } private void UpdateDerived() { if (Drawing != null) { var img = new DrawingImage(Drawing); if (img.CanFreeze) img.Freeze(); SetValue(DrawingImagePropertyKey, img); } else { SetValue(DrawingImagePropertyKey, null); } } private void UpdateEffective() { IconContentType kind; if (ContentType == IconContentType.Auto) { kind = ImageSource != null ? IconContentType.Image : Geometry != null ? IconContentType.Geometry : DrawingBrush != null ? IconContentType.Brush : Drawing != null ? IconContentType.Drawing : !string.IsNullOrEmpty(Glyph) ? IconContentType.Glyph : IconContentType.Material; } else { kind = ContentType; } SetValue(EffectiveContentTypePropertyKey, kind); } /// /// 将给定的字符串名称解析为对应的MaterialSymbol枚举值。 /// 如果提供的字符串为空或无法解析,则返回默认值MaterialSymbol.CR。 /// /// 要解析成MaterialSymbol枚举值的字符串。 /// 与给定字符串名称匹配的MaterialSymbol枚举值,如果无法找到匹配项或输入无效,则返回MaterialSymbol.Cr。 public static MaterialSymbol Parse(string? name) { if (string.IsNullOrEmpty(name)) return MaterialSymbol.CR; try { return (MaterialSymbol)Enum.Parse(typeof(MaterialSymbol), name); } catch { return MaterialSymbol.CR; } } #endregion }