效果如下
上面两个进度条,分别利用了Ellipse或Rectangle的StrokeThickness属性和StrokeDashArray属性,StrokeDashArray是设置边框长度,但要根据StrokeThickness的厚度进行相关于周长的转换。
转换函数如下
/// <summary>
/// 计算进度条百分比
/// </summary>
/// <param name="progress">百分比0-100</param>
/// <param name="radius">圆角的度数</param>
/// <param name="thickness">控件边框厚度</param>
/// <returns></returns>
public static DoubleCollection CalcProgress(double progress, double radius,double thickness)
{
var r = radius - thickness / 2;
var perimeter = 2 * Math.PI * r / thickness;
var step = progress / 100 * perimeter;
var result = new DoubleCollection() { step, 1000 };
return result;
}
下面分别是Ellipse或Rectangle实现的圆形进度条的UI代码
<StackPanel Background="#4E59A4" Orientation="Horizontal">
<Grid Margin="50" Background="Transparent" Width="100" Height="100">
<Ellipse Stroke="Gray" StrokeThickness="12"/>
<Ellipse StrokeThickness="12" StrokeDashArray="{Binding ProcessValue}" RenderTransformOrigin="0.5,0.5">
<Ellipse.Stroke>
<LinearGradientBrush StartPoint="0.5,0.5" EndPoint="0,1">
<GradientStop Offset="1" Color="#B7A227"/>
<GradientStop Offset="0" Color="#0a9644"/>
</LinearGradientBrush>
</Ellipse.Stroke>
<Ellipse.Effect>
<DropShadowEffect BlurRadius="8" ShadowDepth="0" Opacity="1" Color="WhiteSmoke"/>
</Ellipse.Effect>
<Ellipse.RenderTransform>
<RotateTransform Angle="-90"/>
</Ellipse.RenderTransform>
</Ellipse>
<TextBlock Foreground="White" Text="{Binding ProcessNumber}" FontSize="25" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock.Effect>
<DropShadowEffect ShadowDepth="0" BlurRadius="6" Color="White"/>
</TextBlock.Effect>
</TextBlock>
</Grid>
<Grid Margin="50" Background="Transparent" Width="100" Height="100">
<Rectangle Width="100" Height="100" Stroke="LightGray" StrokeThickness="12" RadiusX="50" RadiusY="50"/>
<Rectangle Width="100" Height="100" StrokeThickness="12" RadiusX="50" RadiusY="50" StrokeDashCap="Round" StrokeDashArray="{Binding ProcessValue}" RenderTransformOrigin="0.5,0.5">
<Rectangle.Stroke>
<LinearGradientBrush StartPoint="0.5,0.5" EndPoint="0,1">
<GradientStop Offset="1" Color="#FFCD41"/>
<GradientStop Offset="0" Color="#0a9644"/>
</LinearGradientBrush>
</Rectangle.Stroke>
<Rectangle.Effect>
<DropShadowEffect BlurRadius="8" ShadowDepth="0" Opacity="1" Color="WhiteSmoke"/>
</Rectangle.Effect>
<Rectangle.RenderTransform>
<RotateTransform Angle="90"/>
</Rectangle.RenderTransform>
</Rectangle>
<TextBlock Foreground="White" Text="{Binding ProcessNumber}" FontSize="25" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock.Effect>
<DropShadowEffect ShadowDepth="0" BlurRadius="6" Color="White"/>
</TextBlock.Effect>
</TextBlock>
</Grid>
</StackPanel>
这里我们主要是绑定了一个ProcessValue对象给到Ellipse或Rectangle的StrokeDashArray属性,而ProcessValue对象是一个DoubleCollection类,它表示 System.Double 值的有序集合。最后我们在一个适当的地方更新ProcessValue的值即可。
Task.Run(() =>
{
while (true)
{
Thread.Sleep(1000);
Application.Current.Dispatcher.Invoke(() =>
{
double second = (DateTime.Now.Second * 100) / 60;
ProcessValue = CalcHelper.CalcProgress(second, 50, 12);
ProcessNumber = second + "%";
});
}
});
下面是两个绑定属性的定义
private DoubleCollection doubleCollection = new DoubleCollection() { 0, 1000 };
/// <summary>
/// 圆形进度条数组
/// </summary>
public DoubleCollection ProcessValue
{
get { return doubleCollection; }
set { doubleCollection = value;RaisePropertyChanged("ProcessValue"); }
}
private string processNumber;
/// <summary>
/// 圆形进度条百分比值
/// </summary>
public string ProcessNumber
{
get { return processNumber; }
set { processNumber = value; RaisePropertyChanged("ProcessNumber"); }
}