▪ 前言
项目开发需要,需要做一个圆形的进度条,但是发现 WPF 自带的进度条控件 ProgressBar 无法直接变成圆形,经过不停的Baidu、Google,终于找到了基于 ProgressBar 构建圆形进度条的方法
▪ 效果图
▪ 辅助控件引用
在改造 ProgressBar 控件中,我们将用到 ControlTemplate
模板功能以及 <ed:Arc>
控件。<ed:Arc>
是一个画圆弧的控件(非 WPF 内置的控件),所以我们必须引用进来,否则使用将编译出错。
- .Net 框架的版本必须大于等于 4.0
- 在项目的 引用 中右键 -> 添加引用,在 程序集 -> 扩展 里面找到
Microsoft.Expression.Drawing
勾选引用 - 在窗体的 xaml 文件里的 标签添加如下代码:
xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing"
▪ 改变 ProgressBar 默认模板(基础)
在窗体 xaml 文件里加入如下代码:
<!-- 基于样式的 ControlTemplate 模板资源 -->
<Window.Resources>
<Style x:Key="styleProgressBar" TargetType="{x:Type ProgressBar}">
<Setter Property="Width" Value="100"/>
<Setter Property="Height" Value="100"/>
<Setter Property="Maximum" Value="360"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ProgressBar}">
<Grid Width="100" Height="100" HorizontalAlignment="Center" VerticalAlignment="Top">
<ed:Arc ArcThickness="5" StartAngle="0" Fill="{TemplateBinding Background}" Stretch="None" EndAngle="360"/>
<ed:Arc ArcThickness="5" StartAngle="0" Fill="{TemplateBinding Foreground}" Stretch="None" EndAngle="{TemplateBinding Value}"></ed:Arc>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<ProgressBar Style="{StaticResource styleProgressBar}" Value="240" Foreground="#FF000000" Background="#FFFFFFFF"></ProgressBar>
圆形进度条的值应该是 0 ~ 360 度,所以我们在样式里直接限制 ProgressBar 最大值是 360,宽度和高度根据实际情况设置
以上代码仅仅是构建了圆形进度条,效果图 上标题、剩余时间、备注并没有
▪ 改变 ProgressBar 默认模板(高级)
ProgressBar 控件并没有标题、剩余时间、备注等属性字段,所以在样式的 ControlTemplate
中就不能直接使用 {TemplateBinding ...}
进行属性值的绑定。
所以此处我们将使用 ProgressBar 控件的 DataContext
属性进行数据绑定,在样式的 ControlTemplate
中我们就可以直接使用 {Binding ...}
调用数据。
在窗体 xaml 文件里加入如下代码:
<!-- 基于样式的 ControlTemplate 模板资源 -->
<Window.Resources>
<Style x:Key="styleProgressBar" TargetType="{x:Type ProgressBar}">
<Setter Property="Width" Value="100"/>
<Setter Property="Height" Value="125"/>
<Setter Property="Maximum" Value="360"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ProgressBar}">
<StackPanel Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" Margin="{TemplateBinding Margin}" SnapsToDevicePixels="True">
<Label Height="25" Foreground="#FFFFFFFF" Content="{Binding title}" HorizontalAlignment="Center" VerticalAlignment="Top"></Label>
<Grid Width="75" Height="75" HorizontalAlignment="Center" VerticalAlignment="Top">
<ed:Arc ArcThickness="5" StartAngle="0" Fill="{TemplateBinding Background}" Stretch="None" EndAngle="360"/>
<Label Content="{Binding progress}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center"></Label>
<ed:Arc ArcThickness="5" StartAngle="0" Fill="{TemplateBinding Foreground}" Stretch="None" EndAngle="{TemplateBinding Value}"></ed:Arc>
</Grid>
<Label Height="25" Foreground="#FFFFFFFF" Content="{Binding content}" HorizontalAlignment="Center" VerticalAlignment="Top"></Label>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<!-- ProgressBar 在窗体的 cs 文件中动态创建并追加到 uiProgressBars 中 -->
<WrapPanel x:Name="uiProgressBars"></WrapPanel>
在窗体 cs 文件里加入如下代码:
// 声明圆形进度条的数据对象
class ProgressData
{
public string title { set; get; }
public string content { set; get; }
public string progress { set; get; }
}
// 此段代码防止在窗体 cs 文件的初始化构造函数即可
// 此处代码仅仅做一个范例,你可以循环执行以下代码创建多个圆形进度条
// 也可以通过 WEB SERVICE 获取所需的数据,然后循环创建进度条
ProgressBar pb = new ProgressBar();
ProgressData pd = new ProgressData();
pb.Value = 240;
pb.Style = (Style)FindResource("styleProgressBar");
pb.Foreground = new SolidColorBrush(Color.FromRgb(0,255,0));
pb.Background = new SolidColorBrush(Color.FromRgb(255,255,255));
pd.title = "XX001";
pd.content = "线路板";
pd.progress = "剩余 13 天";
pb.DataContext = pd;
uiProgressBars.Children.Add(pb);