一.前言
申明:WPF自定義控件與樣式是一個系列文章,前後是有些關聯的,但大多是按照由簡到繁的順序逐漸釋出的等,若有不明白的地方可以參考本系列前面的文章,文末附有部分文章連結。
本文主要内容:
- ProcessBar自定義标準樣式;
- ProcessBar自定義環形進度樣式;
二.ProcessBar标準樣式
效果圖:

ProcessBar的樣式非常簡單:
<!--ProgressBar Style-->
<Style TargetType="ProgressBar" x:Key="SimpleProgressBar">
<Setter Property="Background" Value="{StaticResource ControlBorderBrush}" />
<Setter Property="Maximum" Value="1" />
<Setter Property="Value" Value="0" />
<Setter Property="Height" Value="10" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Foreground" Value="{StaticResource FocusBorderBrush}" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="local:ControlAttachProperty.CornerRadius" Value="0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ProgressBar">
<Grid x:Name="Root" >
<Border x:Name="PART_Track" Background="{TemplateBinding Background}"
CornerRadius="{TemplateBinding local:ControlAttachProperty.CornerRadius}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
<Border x:Name="PART_Indicator" HorizontalAlignment="Left" Background="{TemplateBinding Foreground}"
CornerRadius="{TemplateBinding local:ControlAttachProperty.CornerRadius}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="Orientation" Value="Vertical">
<Setter Property="LayoutTransform" TargetName="Root" >
<Setter.Value>
<RotateTransform Angle="-90" />
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
使用示例:
<ProgressBar Margin="5" Value="{Binding Percent,Mode=OneWay}" Style="{StaticResource SimpleProgressBar}" x:Name="pro4"></ProgressBar>
<ProgressBar Margin="5" Value="{Binding Percent,Mode=OneWay}" Height="15" x:Name="pro5" Background="LightSteelBlue" Foreground="OrangeRed"
Style="{StaticResource SimpleProgressBar}"></ProgressBar>
三.ProcessBar環形進度樣式
樣式定義也比較簡單:
<!--注意:該樣式的ProgressBar的最大值為1,,BorderThickness控制環的大小-->
<!--ed需要引用:xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing"-->
<Style x:Key="LoopProcessBar" TargetType="{x:Type ProgressBar}">
<Setter Property="Background" Value="#C1D1DE"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="Width" Value="300"/>
<Setter Property="Height" Value="300"/>
<Setter Property="BorderBrush" Value="BlueViolet"/>
<Setter Property="BorderThickness" Value="60"/>
<Setter Property="Foreground" Value="{StaticResource TextForeground}"/>
<Setter Property="Maximum" Value="1"/>
<Setter Property="Minimum" Value="0"/>
<Setter Property="Value" Value="0"/>
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="IsHitTestVisible" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ProgressBar}">
<Viewbox Stretch="Uniform" VerticalAlignment="Center" HorizontalAlignment="Center">
<Grid Margin="{TemplateBinding Margin}" SnapsToDevicePixels="True" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" >
<!--背景環-->
<ed:Arc Margin="{TemplateBinding Margin}" Opacity="0.6" ArcThickness="{Binding Path=BorderThickness,RelativeSource={RelativeSource TemplatedParent},Mode=OneWay,Converter={x:Static local:XConverter.ThicknessToDoubleConverter}}"
StartAngle="0" Fill="{TemplateBinding Background}" EndAngle="360" Stretch="None" x:Name="arcOuter" />
<!--值-環-->
<ed:Arc Margin="{TemplateBinding Margin}" x:Name="arcValue" ArcThickness="{Binding Path=BorderThickness,RelativeSource={RelativeSource TemplatedParent},Mode=OneWay,Converter={x:Static local:XConverter.ThicknessToDoubleConverter}}"
StartAngle="0" Fill="{TemplateBinding BorderBrush}"
Stretch="None" Panel.ZIndex="2"
EndAngle="{TemplateBinding Value, Converter={x:Static local:XConverter.PercentToAngleConverter}}" >
</ed:Arc>
</Grid>
</Viewbox>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
上面樣式中使用了兩個轉換器:
- ThicknessToDoubleConverter:使用ProcessBar本身的屬性BorderThickness設定環形寬度,把BorderThickness轉換為環Arc寬度所需要的值;
- PercentToAngleConverter:目前進度值轉換為環Arc的角度值;
這個地方有個小技巧,把常用的轉換器聲明為靜态變量,XAML中以"x:Static"方式靜态使用,這樣使用的時候就友善多了,不用xaml中單獨定義了。當然這樣做也有弊端,因為靜态變量本身的特點所決定的,不可濫用。
/// <summary>
/// 百分比轉換為角度值
/// </summary>
public class PercentToAngleConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var percent = value.ToSafeString().ToDouble();
if (percent >= 1) return 360.0D;
return percent * 360;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
/// <summary>
/// 擷取Thickness固定值double
/// </summary>
public class ThicknessToDoubleConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var thickness = (Thickness)value;
return thickness.Left;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return DependencyProperty.UnsetValue;
}
}
使用示例:
<ProgressBar Style="{StaticResource LoopProcessBar}" Value="{Binding Percent,Mode=OneWay}" x:Name="pro1" ></ProgressBar>
<Grid Width="200" Height="200">
<ProgressBar Style="{StaticResource LoopProcessBar}" Value="{Binding Percent,Mode=OneWay}" x:Name="pro2" Margin="0" Width="200" Height="200" BorderThickness="20" BorderBrush="#EF436F"/>
<TextBlock FontSize="30" Text="{Binding Value,Mode=OneWay,ElementName=pro2,StringFormat={}{0:p1}}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
<ProgressBar Style="{StaticResource LoopProcessBar}" x:Name="pro3" Value="{Binding Percent,Mode=OneWay}" Width="100" Height="100" BorderThickness="10" BorderBrush="#EFBF0E"></ProgressBar>
附錄:參考引用
WPF自定義控件與樣式(1)-矢量字型圖示(iconfont)
WPF自定義控件與樣式(2)-自定義按鈕FButton
WPF自定義控件與樣式(3)-TextBox & RichTextBox & PasswordBox樣式、水印、Label标簽、功能擴充
WPF自定義控件與樣式(4)-CheckBox/RadioButton自定義樣式
WPF自定義控件與樣式(5)-Calendar/DatePicker日期控件自定義樣式及擴充
WPF自定義控件與樣式(6)-ScrollViewer與ListBox自定義樣式
WPF自定義控件與樣式(7)-清單控件DataGrid與ListView自定義樣式
WPF自定義控件與樣式(8)-ComboBox與自定義多選控件MultComboBox
WPF自定義控件與樣式(9)-樹控件TreeView與菜單Menu-ContextMenu
版權所有,文章來源:http://www.cnblogs.com/anding
個人能力有限,本文内容僅供學習、探讨,歡迎指正、交流。