WPF 控件自定义模板之:圆形进度条

▪ 前言

项目开发需要,需要做一个圆形的进度条,但是发现 WPF 自带的进度条控件 ProgressBar 无法直接变成圆形,经过不停的Baidu、Google,终于找到了基于 ProgressBar 构建圆形进度条的方法

▪ 效果图

image

▪ 辅助控件引用

在改造 ProgressBar 控件中,我们将用到 ControlTemplate 模板功能以及 <ed:Arc> 控件。<ed:Arc> 是一个画圆弧的控件(非 WPF 内置的控件),所以我们必须引用进来,否则使用将编译出错。

  1. .Net 框架的版本必须大于等于 4.0
  2. 在项目的 引用 中右键 -> 添加引用,在 程序集 -> 扩展 里面找到 Microsoft.Expression.Drawing 勾选引用
  3. 在窗体的 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);
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
WPF 中,可以使用 ed:Arc 控件来绘制圆弧进度条,并设置两端圆角。具体步骤如下: 1. 引入 ed:Arc 命名空间: ```xaml xmlns:ed="http://schemas.efxui.com/xaml" ``` 2. 在 XAML 中使用 ed:Arc 控件,并设置 StrokeStartLineCap 和 StrokeEndLineCap 属性为 Round: ```xaml <ed:Arc Stroke="Gray" StrokeThickness="10" StrokeStartLineCap="Round" StrokeEndLineCap="Round" ArcThickness="10" ArcStart="90" ArcEnd="{Binding Progress}" /> ``` 其中,StrokeStartLineCap 和 StrokeEndLineCap 属性设置线条端点的形状,ArcThickness 属性设置圆弧的宽度,ArcStart 和 ArcEnd 属性设置圆弧的起点和终点。 3. 在 ViewModel 中定义 Progress 属性,并使用 Timer 定时更新进度: ```csharp public class MainWindowViewModel : INotifyPropertyChanged { private int _progress; private Timer _timer; public int Progress { get => _progress; set { if (_progress != value) { _progress = value; OnPropertyChanged(nameof(Progress)); } } } public MainWindowViewModel() { _timer = new Timer(100); _timer.Elapsed += (sender, e) => { Progress += 5; if (Progress > 360) { Progress = 0; } }; _timer.Start(); } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } ``` 完整代码示例: MainWindow.xaml: ```xaml <Window x:Class="WpfApp1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ed="http://schemas.efxui.com/xaml" Title="MainWindow" Height="200" Width="200"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <TextBlock Text="Progress:" Margin="5" /> <ed:Arc Grid.Row="1" Stroke="Gray" StrokeThickness="10" StrokeStartLineCap="Round" StrokeEndLineCap="Round" ArcThickness="10" ArcStart="90" ArcEnd="{Binding Progress}" /> </Grid> </Window> ``` MainWindow.xaml.cs: ```csharp public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); DataContext = new MainWindowViewModel(); } } ``` MainWindowViewModel.cs: ```csharp public class MainWindowViewModel : INotifyPropertyChanged { private int _progress; private Timer _timer; public int Progress { get => _progress; set { if (_progress != value) { _progress = value; OnPropertyChanged(nameof(Progress)); } } } public MainWindowViewModel() { _timer = new Timer(100); _timer.Elapsed += (sender, e) => { Progress += 5; if (Progress > 360) { Progress = 0; } }; _timer.Start(); } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值