WPF 控制元件自定義模板之:圓形進度條
阿新 • • 發佈:2020-12-21
▪ 前言
專案開發需要,需要做一個圓形的進度條,但是發現 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);