ProgressbarStyle.xaml
Home
/
WPF /
Common /
WPF /
Style /
ProgressbarStyle.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:PasswordApp.WPF.Style"
xmlns:converters="clr-namespace:WPF.Common.WPF.Converters">
<Style x:Key="RoundProgressBarStyle" TargetType="{x:Type ProgressBar}"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Style.Resources>
<converters:RoundProgressPathConverter x:Key="RoundProgressPathConverter"/>
<!-- нам понадобится пара констант -->
<!-- доля рабиуса для внутренней части -->
<sys:Double x:Key="RelativeThickness">0.75</sys:Double>
<!-- просто 0 -->
<sys:Double x:Key="Zero">0.0</sys:Double>
<!-- просто 1 -->
<sys:Double x:Key="One">1.0</sys:Double>
<!-- какой процент рисовать для неопределённого состояния -->
<sys:Double x:Key="IndeterminatePart">0.25</sys:Double>
<!-- обычно прогресс по умолчанию зелёный -->
<SolidColorBrush x:Key="ProgressBar.Progress" Color="#FF06B025"/>
<!-- стандартный фон -->
<SolidColorBrush x:Key="ProgressBar.Background" Color="#FFE6E6E6"/>
<!-- стандартный цвет границы -->
<SolidColorBrush x:Key="ProgressBar.Border" Color="#FFBCBCBC"/>
</Style.Resources>
<Setter Property="Foreground" Value="{StaticResource ProgressBar.Progress}"/>
<Setter Property="Background" Value="{StaticResource ProgressBar.Background}"/>
<Setter Property="BorderBrush" Value="{StaticResource ProgressBar.Border}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ProgressBar}">
<Grid x:Name="TemplateRoot">
<!-- в неопределённом состоянии запускаем вращающуюся анимацию -->
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Determinate"/>
<VisualState x:Name="Indeterminate">
<Storyboard RepeatBehavior="Forever">
<DoubleAnimation
Storyboard.TargetProperty="(UIElement.RenderTransform).(RotateTransform.Angle)"
Storyboard.TargetName="Animation"
From="0" To="360" Duration="0:0:2"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<!-- это фон, красим его в цвет фона-->
<Path Fill="{TemplateBinding Background}" Stretch="Uniform"
Stroke="{TemplateBinding BorderBrush}" StrokeThickness="{TemplateBinding BorderThickness}">
<Path.Data>
<MultiBinding Converter="{StaticResource RoundProgressPathConverter}"
ConverterParameter="{StaticResource RelativeThickness}">
<!-- val=1, min=0, max=1 даёт полный круг -->
<Binding Source="{StaticResource One}"/>
<Binding Source="{StaticResource Zero}"/>
<Binding Source="{StaticResource One}"/>
</MultiBinding>
</Path.Data>
</Path>
<Path Fill="{TemplateBinding Foreground}" Stretch="Uniform" Name="Indicator">
<Path.Data>
<MultiBinding Converter="{StaticResource RoundProgressPathConverter}"
ConverterParameter="{StaticResource RelativeThickness}">
<Binding Path="Value" RelativeSource="{RelativeSource TemplatedParent}"/>
<Binding Path="Minimum" RelativeSource="{RelativeSource TemplatedParent}"/>
<Binding Path="Maximum" RelativeSource="{RelativeSource TemplatedParent}"/>
</MultiBinding>
</Path.Data>
</Path>
<!-- это анимировнная штука, будет показываться в неопределённом состоянии -->
<Path Fill="{TemplateBinding Foreground}" Stretch="Uniform" Name="Animation"
Visibility="Collapsed" RenderTransformOrigin="0.5,0.5">
<Path.Data>
<MultiBinding Converter="{StaticResource RoundProgressPathConverter}"
ConverterParameter="{StaticResource RelativeThickness}">
<Binding Source="{StaticResource IndeterminatePart}"/>
<Binding Source="{StaticResource Zero}"/>
<Binding Source="{StaticResource One}"/>
</MultiBinding>
</Path.Data>
<!-- положим пустое вращение, чтобы к нему цеплялась анимация -->
<Path.RenderTransform>
<RotateTransform/>
</Path.RenderTransform>
</Path>
</Grid>
<ControlTemplate.Triggers>
<!-- в случае неопределённого состояния уберём нормальный индикатор и покажем анимацию -->
<Trigger Property="IsIndeterminate" Value="true">
<Setter Property="Visibility" TargetName="Indicator" Value="Collapsed"/>
<Setter Property="Visibility" TargetName="Animation" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>