using System; using System.Diagnostics; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Shapes; namespace MegaRobo.C00225155App.MenuViews.Bottles { public class CircleProgress : Control { static CircleProgress() { DefaultStyleKeyProperty.OverrideMetadata( typeof(CircleProgress), new FrameworkPropertyMetadata(typeof(CircleProgress))); } #region 依赖属性 public double StrokeThickness { get => (double)GetValue(StrokeThicknessProperty); set => SetValue(StrokeThicknessProperty, value); } public static readonly DependencyProperty StrokeThicknessProperty = DependencyProperty.Register("StrokeThickness", typeof(double), typeof(CircleProgress), new PropertyMetadata(8.0, (d, e) => { ((CircleProgress)d).DrawBackgroundPath(); ((CircleProgress)d).UpdateProgressPath(); })); public double Progress { get => (double)GetValue(ProgressProperty); set => SetValue(ProgressProperty, value); } public static readonly DependencyProperty ProgressProperty = DependencyProperty.Register("Progress", typeof(double), typeof(CircleProgress), new PropertyMetadata(0.0, OnProgressChanged)); private static void OnProgressChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((CircleProgress)d).UpdateProgressPath(); } #endregion private Path backgroundPath; private Path progressPath; private TextBlock percentageText; public void ForceRefresh() { UpdateProgressPath(); DrawBackgroundPath(); } public override void OnApplyTemplate() { base.OnApplyTemplate(); backgroundPath = (Path)GetTemplateChild("PART_BackgroundPath"); progressPath = (Path)GetTemplateChild("PART_ProgressPath"); percentageText = (TextBlock)GetTemplateChild("PART_PercentageText"); DrawBackgroundPath(); UpdateProgressPath(); // 订阅 SizeChanged 事件,确保布局完成后重新绘制 SizeChanged += OnSizeChanged; } private void OnSizeChanged(object sender, SizeChangedEventArgs e) { DrawBackgroundPath(); UpdateProgressPath(); } //protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo) //{ // base.OnRenderSizeChanged(sizeInfo); // DrawBackgroundPath(); // UpdateProgressPath(); //} private void DrawBackgroundPath() { if (backgroundPath == null) { Debug.WriteLine("backgroundPath is null"); return; } double strokeThickness = StrokeThickness; double width = ActualWidth > 0 ? ActualWidth : 33; double height = ActualHeight > 0 ? ActualHeight : 33; //double radius = Math.Abs(Math.Min(width, height) / 2 - backgroundPath.StrokeThickness / 2); double radius = Math.Max(0, Math.Min(width, height) / 2 - strokeThickness / 2); double centerX = width / 2; double centerY = height / 2; EllipseGeometry geometry = new EllipseGeometry { Center = new Point(centerX, centerY), RadiusX = radius, RadiusY = radius }; geometry.Freeze(); // 背景圈数据绑定到 backgroundPath backgroundPath.Data = geometry; } private void UpdateProgressPath() { if (progressPath == null || percentageText == null) return; double strokeThickness = StrokeThickness; double width = ActualWidth > 0 ? ActualWidth : 33; double height = ActualHeight > 0 ? ActualHeight : 33; //double radius = Math.Abs(Math.Min(width, height) / 2 - progressPath.StrokeThickness / 2); double radius = Math.Max(0, Math.Min(width, height) / 2 - strokeThickness / 2); double centerX = width / 2; double centerY = height / 2; // 更新百分比文本 percentageText.Text = $"{Progress * 100:F0}%"; // 特殊处理0%和100%的情况 if (Progress >= 1.0) { // 100% - 使用EllipseGeometry绘制完整圆环 progressPath.Data = new EllipseGeometry { Center = new Point(centerX, centerY), RadiusX = radius, RadiusY = radius }; return; } else if (Progress <= 0.0) { // 0% - 创建不可见的微小线段(替代null) var geometry1 = new LineGeometry( new Point(centerX, centerY - radius), new Point(centerX, centerY - radius + 0.01)); progressPath.Data = geometry1; return; } // 正常进度绘制 (0 < Progress < 1) double angle = Progress * 360; bool isLargeArc = angle > 180; Point endPoint = new Point( centerX + radius * Math.Sin(angle * Math.PI / 180), centerY - radius * Math.Cos(angle * Math.PI / 180) ); PathGeometry geometry = new PathGeometry(); PathFigure figure = new PathFigure { StartPoint = new Point(centerX, centerY - radius), IsClosed = false }; figure.Segments.Add(new ArcSegment { Point = endPoint, Size = new Size(radius, radius), IsLargeArc = isLargeArc, SweepDirection = SweepDirection.Clockwise, RotationAngle = 0 }); geometry.Figures.Add(figure); progressPath.Data = geometry; } } }