這篇文章主要介紹了c# 如何實現圓形的進度條(ProgressBar),幫助大家更好的理解和學習使用c#,感興趣的朋友可以了解下在我們實際的工作中可能經常使用到圓形的進度條,但是這c#教學是怎麼實現的呢?其實這只不過是修改了一下ProgressBar的模板,我們在下面的程式碼中我們將ProgressBar的Value值繫結到Border的Background上面,並且使用了一個ValueToProcessConverter的轉換器進行相應地轉換,這裡重點介紹一下這個轉換器
1 2 3 4 5 6 7 | <ProgressBar Name="pb" Minimum="0" Maximum="100" > <ProgressBar.Template> <ControlTemplate TargetType="ProgressBar"> <Border Background="{TemplateBinding Value, Converter={StaticResource ValueToProcessConverter}, ConverterParameter=250}"/> </ControlTemplate> </ProgressBar.Template> </ProgressBar> |
下面介紹這部分的原始碼,並做簡要的分析:
1 | 首先,取得ProgressBar.Value,然後再取得ConverterParameter=250這個值,透過這兩個值就能確定畫的圓環的大小和ProgressBar顯示的值,然後我們再呼叫DrawBrush(arg, 100, radius, radius, Thickness)這個函式來進行繪製,具體程式碼如下: |
1 2 3 4 5 6 7 8 | private Brush DrawBrush(double value, double maxValue, double radiusX, double radiusY, double thickness) {<!-- --> DrawingGroup drawingGroup = new DrawingGroup(); DrawingContext drawingContext = drawingGroup.Open(); DrawingGeometry(drawingContext, value, maxValue, radiusX, radiusY, thickness); DrawingBrush brush = new DrawingBrush(drawingGroup); return brush; } |
這裡需要注意的是絕不能直接例項化 DrawingContext;但可以透過某些方法(例如 DrawingGroup.Open 和 DrawingVisual.RenderOpen)取得繪圖上下文。我們這裡是使用DrawingGroup.Open的方法來進行相應的繪圖,然後在裡面呼叫里DrawingGeometry這個函式,在這個函式中開始繪製一些DrawEllipse和DrawGeometry,在這個函式中我們講解一下FormattedText 這個類,使用 FormattedText 物件可以繪製多行文字,且可以單獨對該文字中的每個字元設定格式。
1 2 3 4 5 6 7 8 9 10 11 | private void DrawingGeometry(DrawingContext drawingContext, double value, double maxValue, double radiusX, double radiusY, double thickness) {<!-- --> drawingContext.DrawEllipse(null, new Pen(EllipseBrush, thickness), centerPoint, radiusX, radiusY); drawingContext.DrawGeometry(NormalBrush, new Pen(), GetGeometry(value, maxValue, radiusX, radiusY, thickness)); FormattedText formatWords = new FormattedText(percentString, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, SuccessRateTypeface, SuccessRateFontSize, NormalBrush); Point startPoint = new Point(centerPoint.X - formatWords.Width / 2, centerPoint.Y - formatWords.Height / 2 - SuccessRateFontCorrectionValue); drawingContext.DrawText(formatWords, startPoint); drawingContext.Close(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | public class ValueToProcessConverter : IValueConverter {<!-- --> readonly double Thickness = 20; private Point centerPoint; private double radius; readonly SolidColorBrush NormalBrush = new SolidColorBrush(Colors.White); readonly SolidColorBrush EllipseBrush = new SolidColorBrush(Color.FromRgb(107, 132, 165)); string percentString; private static readonly Typeface SuccessRateTypeface; private const int SuccessRateFontSize = 65; readonly double SuccessRateFontCorrectionValue = 12; static ValueToProcessConverter() {<!-- --> SuccessRateTypeface = new Typeface(new FontFamily("MSYH"), new FontStyle(), new FontWeight(), new FontStretch()); } public ValueToProcessConverter() {<!-- --> } public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {<!-- --> if (value is double && !string.IsNullOrEmpty((string)parameter)) {<!-- --> double arg = (double)value; double width = double.Parse((string)parameter); radius = width / 2; centerPoint = new Point(radius, radius); return DrawBrush(arg, 100, radius, radius, Thickness); } else {<!-- --> throw new ArgumentException(); } } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {<!-- --> throw new NotImplementedException(); } /// <summary> /// 根據角度取得坐標 /// </summary> /// <param name="CenterPoint"></param> /// <param name="r"></param> /// <param name="angel"></param> /// <returns></returns> private Point GetPointByAngel(Point CenterPoint, double r, double angel) {<!-- --> Point p = new Point(); p.X = Math.Sin(angel * Math.PI / 180) * r + CenterPoint.X; p.Y = CenterPoint.Y - Math.Cos(angel * Math.PI / 180) * r; return p; } /// <summary> /// 根據4個坐標畫出扇形 /// </summary> /// <param name="bigFirstPoint"></param> /// <param name="bigSecondPoint"></param> /// <param name="smallFirstPoint"></param> /// <param name="smallSecondPoint"></param> /// <param name="bigRadius"></param> /// <param name="smallRadius"></param> /// <param name="isLargeArc"></param> /// <returns></returns> private Geometry DrawingArcGeometry(Point bigFirstPoint, Point bigSecondPoint, Point smallFirstPoint, Point smallSecondPoint, double bigRadius, double smallRadius, bool isLargeArc) {<!-- --> PathFigure pathFigure = new PathFigure {<!-- --> IsClosed = true }; pathFigure.StartPoint = bigFirstPoint; pathFigure.Segments.Add( new ArcSegment {<!-- --> Point = bigSecondPoint, IsLargeArc = isLargeArc, Size = new Size(bigRadius, bigRadius), SweepDirection = SweepDirection.Clockwise }); pathFigure.Segments.Add(new LineSegment {<!-- --> Point = smallSecondPoint }); pathFigure.Segments.Add( new ArcSegment {<!-- --> Point = smallFirstPoint, IsLargeArc = isLargeArc, Size = new Size(smallRadius, smallRadius), SweepDirection = SweepDirection.Counterclockwise }); PathGeometry pathGeometry = new PathGeometry(); pathGeometry.Figures.Add(pathFigure); return pathGeometry; } /// <summary> /// 根據當前值和最大值取得扇形 /// </summary> /// <param name="value"></param> /// <param name="maxValue"></param> /// <returns></returns> private Geometry GetGeometry(double value, double maxValue, double radiusX, double radiusY, double thickness) {<!-- --> bool isLargeArc = false; double percent = value / maxValue; percentString = string.Format("{0}%", Math.Round(percent * 100, 2)); double angel = percent * 360D; if (angel > 180) isLargeArc = true; double bigR = radiusX + thickness / 2; double smallR = radiusX - thickness / 2; Point firstpoint = GetPointByAngel(centerPoint, bigR, 0); Point secondpoint = GetPointByAngel(centerPoint, bigR, angel); Point thirdpoint = GetPointByAngel(centerPoint, smallR, 0); Point fourpoint = GetPointByAngel(centerPoint, smallR, angel); return DrawingArcGeometry(firstpoint, secondpoint, thirdpoint, fourpoint, bigR, smallR, isLargeArc); } /// <summary> /// 畫扇形 /// </summary> /// <param name="drawingContext"></param> /// <param name="value"></param> /// <param name="maxValue"></param> /// <param name="radiusX"></param> /// <param name="radiusY"></param> /// <param name="thickness"></param> private void DrawingGeometry(DrawingContext drawingContext, double value, double maxValue, double radiusX, double radiusY, double thickness) {<!-- --> drawingContext.DrawEllipse(null, new Pen(EllipseBrush, thickness), centerPoint, radiusX, radiusY); drawingContext.DrawGeometry(NormalBrush, new Pen(), GetGeometry(value, maxValue, radiusX, radiusY, thickness)); FormattedText formatWords = new FormattedText(percentString, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, SuccessRateTypeface, SuccessRateFontSize, NormalBrush); Point startPoint = new Point(centerPoint.X - formatWords.Width / 2, centerPoint.Y - formatWords.Height / 2 - SuccessRateFontCorrectionValue); drawingContext.DrawText(formatWords, startPoint); drawingContext.Close(); } /// <summary> /// 根據當前值和最大值畫出進度條 /// </summary> /// <param name="value"></param> /// <param name="maxValue"></param> /// <returns></returns> private Brush DrawBrush(double value, double maxValue, double radiusX, double radiusY, double thickness) {<!-- --> DrawingGroup drawingGroup = new DrawingGroup(); DrawingContext drawingContext = drawingGroup.Open(); DrawingGeometry(drawingContext, value, maxValue, radiusX, radiusY, thickness); DrawingBrush brush = new DrawingBrush(drawingGroup); return brush; } } |
以上就是c# 實現圓形的進度條(ProgressBar)的詳細內容