WPF实现圆形进度条框架使用.NET40;VisualStudio2019;CircularProgressBar继承ProgressBar,在XAML中创建两个Path的Data设置ArcSe...
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="{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 代码如下:
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;
_arcSegment.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进度条内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!










