WPF實現(xiàn)圓形進度條的示例代碼
WPF 實現(xiàn)圓形進度條
- 框架使用
.NET40; Visual Studio 2019;CircularProgressBar繼承ProgressBar,在XAML中創(chuàng)建兩個Path的Data設置ArcSegment修改第二個控件的Point,設置StartPoint = new Point(Size.Width, 0)設置起點。- 創(chuàng)建依賴屬性
Angle作為修改ArcSegment的Point作為進度條的圓的閉合。 - 當進度條
ValueChanged時創(chuàng)建DoubleAnimation動畫,修改Angle。
示例代碼
1) CircularProgressBar.xaml 代碼如下:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:WPFDevelopers.Controls"
xmlns:convert="clr-namespace:WPFDevelopers.Converts">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Basic/ControlBasic.xaml"/>
</ResourceDictionary.MergedDictionaries>
<convert:AngleToPointConverter x:Key="prConverter"/>
<convert:AngleToIsLargeConverter x:Key="isLargeConverter"/>
<Style TargetType="{x:Type controls:CircularProgressBar}" BasedOn="{StaticResource ControlBasicStyle}">
<Setter Property="Maximum" Value="100"/>
<Setter Property="StrokeThickness" Value="10"/>
<Setter Property="Foreground" Value="{DynamicResource InfoSolidColorBrush}"/>
<Setter Property="Background" Value="{DynamicResource PrimaryNormalSolidColorBrush}"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<!--<Setter Property="Width" Value="100"/>
<Setter Property="Height" Value="100"/>-->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls:CircularProgressBar}">
<controls:SmallPanel Width="{Binding ElementName=PART_Path,Path=ActualWidth}"
Height="{Binding ElementName=PART_Path,Path=ActualHeight}"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
VerticalAlignment="{TemplateBinding VerticalAlignment}">
<Canvas>
<Path Stroke="{TemplateBinding BorderBrush}"
StrokeThickness="{TemplateBinding BrushStrokeThickness}"
x:Name="PART_Path">
<Path.Data>
<PathGeometry>
<PathFigure x:Name="PART_PathFigure">
<ArcSegment SweepDirection="Clockwise"
IsLargeArc="True"
x:Name="PART_ArcSegment">
</ArcSegment>
</PathFigure>
</PathGeometry>
</Path.Data>
</Path>
<Path Stroke="{TemplateBinding Background}"
StrokeThickness="{TemplateBinding StrokeThickness}">
<Path.Data>
<PathGeometry>
<PathFigure x:Name="PART_PathFigureAngle">
<ArcSegment SweepDirection="Clockwise"
IsLargeArc="{Binding Path=Angle, Converter={StaticResource isLargeConverter}, RelativeSource={RelativeSource FindAncestor, AncestorType=ProgressBar}}"
x:Name="PART_ArcSegmentAngle">
<ArcSegment.Point>
<MultiBinding Converter="{StaticResource prConverter}">
<Binding Path="Angle" RelativeSource="{RelativeSource FindAncestor, AncestorType=ProgressBar}"/>
<Binding Path="Size" RelativeSource="{RelativeSource FindAncestor, AncestorType=ProgressBar}"/>
</MultiBinding>
</ArcSegment.Point>
</ArcSegment>
</PathFigure>
</PathGeometry>
</Path.Data>
</Path>
</Canvas>
<TextBlock Foreground="{TemplateBinding Foreground}"
Text="{Binding Path=Value, StringFormat={}{0}%,
RelativeSource={RelativeSource TemplatedParent}}"
FontSize="{TemplateBinding FontSize}"
VerticalAlignment="Center"
HorizontalAlignment="Center"
x:Name="PART_TextBlock"/>
</controls:SmallPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>2) CircularProgressBar.xaml.cs 代碼如下:
using?System;
using?System.Windows;
using?System.Windows.Controls;
using?System.Windows.Media;
using?System.Windows.Media.Animation;
namespace?WPFDevelopers.Controls
{
????[TemplatePart(Name?=?ArcSegmentTemplateName,?Type?=?typeof(ArcSegment))]
????[TemplatePart(Name?=?ArcSegmentAngleTemplateName,?Type?=?typeof(ArcSegment))]
????[TemplatePart(Name?=?PathFigureTemplateName,?Type?=?typeof(PathFigure))]
????[TemplatePart(Name?=?PathFigureAngleTemplateName,?Type?=?typeof(PathFigure))]
????[TemplatePart(Name?=?TextBlockTemplateName,?Type?=?typeof(TextBlock))]
????public?class?CircularProgressBar?:?ProgressBar
????{
????????private?const?string?ArcSegmentTemplateName?=?"PART_ArcSegment";
????????private?const?string?ArcSegmentAngleTemplateName?=?"PART_ArcSegmentAngle";
????????private?const?string?PathFigureTemplateName?=?"PART_PathFigure";
????????private?const?string?PathFigureAngleTemplateName?=?"PART_PathFigureAngle";
????????private?const?string?TextBlockTemplateName?=?"PART_TextBlock";
????????private?ArcSegment?_arcSegment,?_arcSegmentAngle;
????????private?PathFigure?_pathFigure,?_pathFigureAngle;
????????private?TextBlock?_textBlock;
????????public?static?readonly?DependencyProperty?SizeProperty?=
???????????DependencyProperty.Register("Size",?typeof(Size),?typeof(CircularProgressBar),
???????????????new?PropertyMetadata(new?Size(50,50)));
????????public?static?readonly?DependencyProperty?AngleProperty?=
????????????DependencyProperty.Register("Angle",?typeof(double),?typeof(CircularProgressBar),
????????????????new?PropertyMetadata(0.0));
????????public?static?readonly?DependencyProperty?StrokeThicknessProperty?=
????????????DependencyProperty.Register("StrokeThickness",?typeof(double),?typeof(CircularProgressBar),
????????????????new?PropertyMetadata(10.0));
????????public?static?readonly?DependencyProperty?BrushStrokeThicknessProperty?=
????????????DependencyProperty.Register("BrushStrokeThickness",?typeof(double),?typeof(CircularProgressBar),
????????????????new?PropertyMetadata(1.0));
????????public?CircularProgressBar()
????????{
????????????ValueChanged?+=?CircularProgressBar_ValueChanged;
????????}
????????public?override?void?OnApplyTemplate()
????????{
????????????base.OnApplyTemplate();
???????????
????????????if?(Size.Width?!=?Size.Height)
????????????{
????????????????var?max?=?Math.Max(Size.Width,?Size.Height);
????????????????Size?=?new?Size(max,?max);
????????????}
???????????
????????????_pathFigure?=?GetTemplateChild(PathFigureTemplateName)?as?PathFigure;
????????????_pathFigureAngle?=?GetTemplateChild(PathFigureAngleTemplateName)?as?PathFigure;
????????????_pathFigure.StartPoint?=?new?Point(Size.Width,?0);
????????????_pathFigureAngle.StartPoint?=?new?Point(Size.Width,?0);
????????????_arcSegment?=?GetTemplateChild(ArcSegmentTemplateName)?as?ArcSegment;
????????????_arcSegment.Size?=?Size;
????????????_arcSegment.Point?=?new?Point(Size.Width?-?0.000872664626,?7.61543361704753E-09);
????????????_arcSegmentAngle?=?GetTemplateChild(ArcSegmentAngleTemplateName)?as?ArcSegment;
????????????_arcSegmentAngle.Size?=?Size;
????????????_textBlock?=?GetTemplateChild(TextBlockTemplateName)?as?TextBlock;
????????????if?(Size.Width?<?15)
????????????{
????????????????FontSize?=?8;
????????????}
????????}
????????
????????public?Size?Size
????????{
????????????get?=>?(Size)GetValue(SizeProperty);
????????????set?=>?SetValue(SizeProperty,?value);
????????}
????????public?double?Angle
????????{
????????????get?=>?(double)GetValue(AngleProperty);
????????????set?=>?SetValue(AngleProperty,?value);
????????}
????????public?double?StrokeThickness
????????{
????????????get?=>?(double)GetValue(StrokeThicknessProperty);
????????????set?=>?SetValue(StrokeThicknessProperty,?value);
????????}
????????public?double?BrushStrokeThickness
????????{
????????????get?=>?(double)GetValue(BrushStrokeThicknessProperty);
????????????set?=>?SetValue(BrushStrokeThicknessProperty,?value);
????????}
????????private?void?CircularProgressBar_ValueChanged(object?sender,?RoutedPropertyChangedEventArgs<double>?e)
????????{
????????????var?bar?=?sender?as?CircularProgressBar;
????????????var?currentAngle?=?bar.Angle;
????????????var?targetAngle?=?e.NewValue?/?bar.Maximum?*?359.999;
????????????var?anim?=?new?DoubleAnimation(currentAngle,?targetAngle,?TimeSpan.FromMilliseconds(500));
????????????bar.BeginAnimation(AngleProperty,?anim,?HandoffBehavior.SnapshotAndReplace);
????????}
????}
}
3) AngleToPointConverter.cs 代碼如下:
using?System;
using?System.Globalization;
using?System.Windows;
using?System.Windows.Data;
namespace?WPFDevelopers.Converts
{
????internal?class?AngleToPointConverter?:?IMultiValueConverter
????{
????????public?object?Convert(object[]?values,?Type?targetType,?object?parameter,?CultureInfo?culture)
????????{
????????????var?angle?=?(double)values[0];
????????????var?size?=?(Size)values[1];
????????????var?radius?=?(double)size.Height;
????????????var?piang?=?angle?*?Math.PI?/?180;
????????????var?px?=?Math.Sin(piang)?*?radius?+?radius;
????????????var?py?=?-Math.Cos(piang)?*?radius?+?radius;
????????????return?new?Point(px,?py);
????????}
????????public?object[]?ConvertBack(object?value,?Type[]?targetTypes,?object?parameter,?CultureInfo?culture)
????????{
????????????throw?new?NotImplementedException();
????????}
????}
}
4) AngleToIsLargeConverter.cs 代碼如下:
using?System;
using?System.Globalization;
using?System.Windows.Data;
namespace?WPFDevelopers.Converts
{
????internal?class?AngleToIsLargeConverter?:?IValueConverter
????{
????????public?object?Convert(object?value,?Type?targetType,?object?parameter,?CultureInfo?culture)
????????{
????????????var?angle?=?(double)value;
????????????return?angle?>?180;
????????}
????????public?object?ConvertBack(object?value,?Type?targetTypes,?object?parameter,?CultureInfo?culture)
????????{
????????????throw?new?NotImplementedException();
????????}
????}
}
5) CircularMenuExample.xaml 代碼如下:
<UserControl?x:Class="WPFDevelopers.Samples.ExampleViews.CircularMenuExample"
?????????????xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
?????????????xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
?????????????xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"?
?????????????xmlns:d="http://schemas.microsoft.com/expression/blend/2008"?
?????????????xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews"
?????????????xmlns:wpfdev="https://github.com/WPFDevelopersOrg/WPFDevelopers"
?????????????xmlns:controls="clr-namespace:WPFDevelopers.Samples.Controls"
?????????????mc:Ignorable="d"?
?????????????d:DesignHeight="450"?d:DesignWidth="800">
????<controls:CodeViewer>
????????<StackPanel?Background="Black">
????????<TextBlock?Text="微信公眾號:WPFDevelopers"?FontSize="40"
???????????????????????????Foreground="#A9CC32"?FontWeight="Bold"
???????????????????????????Margin="50,10,0,20"/>
????????<wpfdev:CircularMenu?ItemsSource="{Binding?MenuArray,RelativeSource={RelativeSource?AncestorType=local:CircularMenuExample}}"?
?????????????????????????????SelectionChanged="CircularMenu_SelectionChanged"/>
????</StackPanel>
????????<controls:CodeViewer.SourceCodes>
????????????<controls:SourceCodeModel?
????????????????CodeSource="/WPFDevelopers.SamplesCode;component/ExampleViews/CircularMenuExample.xaml"?
????????????????CodeType="Xaml"/>
????????????<controls:SourceCodeModel?
????????????????CodeSource="/WPFDevelopers.SamplesCode;component/ExampleViews/CircularMenuExample.xaml.cs"?
????????????????CodeType="CSharp"/>
????????</controls:CodeViewer.SourceCodes>
????</controls:CodeViewer>
</UserControl>效果圖

到此這篇關于WPF實現(xiàn)圓形進度條的示例代碼的文章就介紹到這了,更多相關WPF進度條內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
C#實現(xiàn)Excel轉PDF時設置內容適應頁面寬度
將Excel轉為PDF格式時,通常情況下轉換出來的PDF頁面都是默認的寬度大小。所以本文提供了C#實現(xiàn)Excel轉PDF時設置內容適應頁面寬度的示例代碼,需要的可以參考一下2022-04-04
WinForm實現(xiàn)基于BindingSource的方法擴展
這篇文章主要介紹了WinForm實現(xiàn)基于BindingSource的方法擴展,需要的朋友可以參考下2014-08-08
C#基礎知識之GetType與typeof的區(qū)別小結
在比較對象時,需要了解他們的類型,才能決定他們的值是否能比較。所有的類都從System.Object中繼承了GetType()方法,常常與typeo()運算符一起使用。這篇文章主要給大家介紹了關于C#基礎知識之GetType與typeof區(qū)別的相關資料,需要的朋友可以參考下2021-06-06

