C00225155-02/C00225155/MegaRobo.C00225155/MegaRobo.C00225155App/MenuViews/Bottles/CircleProgress.cs

183 lines
6.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
}
}
}