1. 程式人生 > 其它 >WPF 控制元件自定義模板之:圓形進度條

WPF 控制元件自定義模板之:圓形進度條

技術標籤:桌面軟體C#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);