wpF 实现圆形进度条
- 框架使用
.NET40
; Visual Studio 2019
;CircularProgressBar
继承ProgressBar
,在XAML
中创建两个Path
的Data
设置ArcSegment
修改第二个控件的Point
,设置StartPoint = new Point(Size.Width, 0)
设置起点。- 创建依赖属性
Angle
作为修改ArcSegment
的Point
作为进度条的圆的闭合。 - 当进度条
ValueChanged
时创建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="{DyphpnamicResourc开发者_C教程e 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> </PathGeometrjavascripty> </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=Progre编程ssBar}}" 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
代码如下:
usingSystem; usingSystem.Windows; usingSystem.Windows.Controls; usingSystem.Windows.Media; usingSystem.Windows.Media.Animation; namespaceWPFDevelopers.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))] publicclassCircularProgressBar:ProgressBar { privateconststringArcSegmentTemplateName="PART_ArcSegment"; privateconststringArcSegmentAngleTemplateName="PART_ArcSegmentAngle"; privateconststringPathFigureTemplateName="PART_PathFigure"; privateconststringPathFigureAngleTemplateName="PART_PathFigureAngle"; privateconststringTextBlockTemplateName="PART_TextBlock"; privateArcSegment_arcSegment,_arcSegmentAngle; privatePathFigure_pathFigure,_pathFigureAngle; privateTextBlock_textBlock; publicstaticreadonlyDependencyPropertySizeProperty= DependencyProperty.Register("Size",typeof(Size),typeof(CircularProgressBar), newPropertyMetadata(newSize(50,50))); publicstaticreadonlyDependencyPropertyAngleProperty= DependencyProperty.Register("Angle",typeof(double),typeof(CircularProgressBar), newPropertyMetadata(0.0)); publicstaticreadonlyDependencyPropertyStrokeThicknessProperty= DependencyProperty.Register("StrokeThickness",typeof(double),typeof(CircularProgressBar), newPropertyMetadata(10.0)); publicstaticreadonlyDependencyPropertyBrushStrokeThicknessProperty= DependencyProperty.Register("BrushStrokeThickness",typeof(double),typeof(CircularProgressBar), newPropertyMetadata(1.0)); publicCircularProgressBar() { ValueChanged+=CircularProgressBar_ValueChanged; } publicoverridevoidOnApplyTemplate() { base.OnApplyTemplate(); if(Size.Width!=Size.Height) { varmax=Math.Max(Size.Width,Size.Height); Size=newSize(max,max); } _pathFigure=GetTemplateChild(PathFigureTemplateName)ASPathFigure; _pathFigureAngle=GetTemplateChild(PathFigureAngleTemplateName)asPathFigure; _pathFigure.StartPoint=newPoint(Size.Width,0); _pathFigureAngle.StartPoint=newPoint(Size.Width,0); _arcSegment=GetTemplateChild(ArcSegmentTemplateName)asArcSegment; _arcSegmphpent.Size=Size; _arcSegment.Point=newPoint(Size.Width-0.000872664626,7.61543361704753E-09); _arcSegmentAngle=GetTemplateChild(ArcSegmentAngleTemplateName)asArcSegment; _arcSegmentAngle.Size=Size; _textBlock=GetTemplateChild(TextBlockTemplateName)asTextBlock; if(Size.Width<15) { FontSize=8; } } publicSizeSize { get=>(Size)GetValue(SizeProperty); set=>SetValue(SizeProperty,value); } publicdoubleAngle { get=>(double)GetValue(AngleProperty); set=>SetValue(AngleProperty,value); } publicdoubleStrokeThickness { get=>(double)GetValue(StrokeThicknessProperty); set=>SetValue(StrokeThicknessProperty,value); } publicdoubleBrushStrokeThickness { get=>(double)GetValue(BrushStrokeThicknessProperty); set=>SetValue(BrushStrokeThicknessProperty,value); } privatevoidCircularProgressBar_ValueChanged(objectsender,RoutedPropertyChangedEventArgs<double>e) { varbar=senderasCircularProgressBar; varcurrentAngle=bar.Angle; vartargetAngle=e.NewValue/bar.Maximum*359.999; varanim=newDoubleAnimation(currentAngle,targetAngle,TimeSpan.FromMilliseconds(500)); bar.BeginAnimation(AngleProperty,anim,HandoffBehavior.SnapshotAndReplace); } } }
3) AngleToPointConverter.cs
代码如下:
usingSystem; usingSystem.Globalization; usingSystem.Windows; usingSystem.Windows.Data; namespaceWPFDevelopers.Converts { internalclassAngleToPointConverter:IMultiValueConverter { publicobjectConvert(object[]values,TypetargetType,objectparameter,CultureInfoculture) { varangle=(double)values[0]; varsize=(Size)values[1]; varradius=(double)size.Height; varpiang=angle*Math.PI/180; varpx=Math.Sin(piang)*radius+radius; varpy=-Math.Cos(piang)*radius+radius; returnnewPoint(px,py); } publicobject[]ConvertBack(objectvalue,Type[]targetTypes,objectparameter,CultureInfoculture) { thrownewNotImplementedException(); } } }
4) AngleToIsLargeConverter.cs
代码如下:
usingSystem; usingSystem.Globalization; usingSystem.Windows.Data; namespaceWPFDevelopers.Converts { internalclassAngleToIsLargeConverter:IValueConverter { publicobjectConvert(objectvalue,TypetargetType,objectparameter,CultureInfoculture) { varangle=(double)value; returnangle>180; } publicobjectConvertBack(objectvalue,TypetargetTypes,objectparameter,CultureInfoculture) { thrownewNotImplementedException(); } } }
5) CircularMenuExample.xaml
代码如下:
<UserControlx: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> <StackPanelBackground="Black"> <TextBlockText="微信公众号:WPFDevelopers"FontSize="40" Foreground="#A9CC32"FontWeight="Bold" Margin="50,10,0,20"/> <wpfdev:CircularMenuItemsSource="{BindingMenuArray,RelativeSource={RelativeSourceAncestorType=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实现圆形进度条的示例代码的文章就介绍到这了,更多相关WPF进度条内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!
精彩评论