Fork me on GitHub

加载进度-【圆圈+百分比】

为了增加用户体验,我们在打打开较大的文件,或者在一些耗时的操作中,我们可以通过增加进度条,保证更好的用户提体验

以下主要展示的是圆圈+百分比的一个加载进度模板

设计代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<Grid Panel.ZIndex="-1" Visibility="{Binding LoadingVisibility}">
    <Grid.RowDefinitions>
 
        <RowDefinition Height="30"></RowDefinition>
        <RowDefinition></RowDefinition>
    </Grid.RowDefinitions>
 
    <Label Name="lbShow" Grid.Row="0"  HorizontalAlignment="Left" Margin="38,5,0,0" VerticalAlignment="Top"  RenderTransformOrigin="-0.375,0.3"/>
    <ProgressBar Name="pbBar" Grid.Row="1"  Minimum="0"
                 Maximum="100"
                 Value="{Binding LoaddingPercent, Mode=OneWay}" Height="120" Width="120" >
        <ProgressBar.Template>
            <ControlTemplate TargetType="ProgressBar">
                <Border Background="{TemplateBinding Value, Converter={StaticResource ValueToProcessConverter}, ConverterParameter=200}"/>
            </ControlTemplate>
        </ProgressBar.Template>
    </ProgressBar>
</Grid>

  我们需要将数据转换成ProgressBar的需要的值,因此需要转换器,代码如下

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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
public class ValueToProcessConverter : IValueConverter
   {
       private const double Thickness = 8;
       private const double Padding = 1;
       private const double WarnValue = 60;
       private const int SuccessRateFontSize = 34;
       private static readonly SolidColorBrush NormalBrush;
       private static readonly SolidColorBrush WarnBrush;
       private static readonly Typeface SuccessRateTypeface;
 
       private string percentString;
       private Point centerPoint;
       private double radius;
 
       static ValueToProcessConverter()
       {
           NormalBrush = new SolidColorBrush(Colors.Green);
           WarnBrush = new SolidColorBrush(Colors.Red);
           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, Padding);
           }
           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, double padding)
       {
           bool isLargeArc = false;
           double percent = value / maxValue;
           percentString = string.Format("{0}%", Math.Round(percent * 100));
           double angel = percent * 360D;
           if (angel > 180) isLargeArc = true;
           double bigR = radiusX;
           double smallR = radiusX - thickness + padding;
           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);
       }
 
       private void DrawingGeometry(DrawingContext drawingContext, double value, double maxValue, double radiusX, double radiusY, double thickness, double padding)
       {
           if (value != maxValue)
           {
               SolidColorBrush brush;
               if (value < WarnValue)
               {
                   brush = WarnBrush;
               }
               else
               {
                   brush = NormalBrush;
               }
               drawingContext.DrawEllipse(null, new Pen(new SolidColorBrush(Color.FromRgb(0xdd, 0xdf, 0xe1)), thickness), centerPoint, radiusX, radiusY);
               drawingContext.DrawGeometry(brush, new Pen(), GetGeometry(value, maxValue, radiusX, radiusY, thickness, padding));
               FormattedText formatWords = new FormattedText(percentString,
                   CultureInfo.CurrentCulture,
                   FlowDirection.LeftToRight,
                   SuccessRateTypeface,
                   SuccessRateFontSize,
                   brush);
               Point startPoint = new Point(centerPoint.X - formatWords.Width / 2, centerPoint.Y - formatWords.Height / 2);
               drawingContext.DrawText(formatWords, startPoint);
           }
           else
           {
               drawingContext.DrawEllipse(null, new Pen(NormalBrush, thickness), centerPoint, radiusX, radiusY);
               FormattedText formatWords = new FormattedText("100%",
                   CultureInfo.CurrentCulture,
                   FlowDirection.LeftToRight,
                   SuccessRateTypeface,
                   SuccessRateFontSize,
                   NormalBrush);
               Point startPoint = new Point(centerPoint.X - formatWords.Width / 2, centerPoint.Y - formatWords.Height / 2);
               drawingContext.DrawText(formatWords, startPoint);
           }
 
           drawingContext.Close();
       }
 
       /// <summary>
       /// 根据当前值和最大值画出进度条
       /// </summary>
       /// <param name="value"></param>
       /// <param name="maxValue"></param>
       /// <returns></returns>
       private Visual DrawShape(double value, double maxValue, double radiusX, double radiusY, double thickness, double padding)
       {
           DrawingVisual drawingWordsVisual = new DrawingVisual();
           DrawingContext drawingContext = drawingWordsVisual.RenderOpen();
 
           DrawingGeometry(drawingContext, value, maxValue, radiusX, radiusY, thickness, padding);
 
           return drawingWordsVisual;
       }
 
       /// <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, double padding)
       {
           DrawingGroup drawingGroup = new DrawingGroup();
           DrawingContext drawingContext = drawingGroup.Open();
 
           DrawingGeometry(drawingContext, value, maxValue, radiusX, radiusY, thickness, padding);
 
           DrawingBrush brush = new DrawingBrush(drawingGroup);
 
           return brush;
       }
 
   }

  对应的viewModel中只需要添加对应的属性

1
2
3
4
5
6
7
8
9
10
11
/// <summary>
/// propfull
/// 加载进度
/// </summary>
private double loaddingPercent;
 
public double LoaddingPercent
{
    get { return loaddingPercent; }
    set { loaddingPercent = value; OnPropertyChanged(); }
}

  最终效果如下:

 

posted @   黄高林  阅读(136)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
点击右上角即可分享
微信分享提示