加载进度-【圆圈+百分比】
为了增加用户体验,我们在打打开较大的文件,或者在一些耗时的操作中,我们可以通过增加进度条,保证更好的用户提体验
以下主要展示的是圆圈+百分比的一个加载进度模板
设计代码如下:
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(); } } |
最终效果如下:
标签:
.net、WPF
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗