开发者

WPF实现圆形进度条的示例代码

开发者 https://www.devze.com 2023-01-04 10:44 出处:网络 作者: 驚鏵
wpF 实现圆形进度条 框架使用.NET40;Visual Studio 2019;CircularProgressBar 继承 ProgressBar,在 XAML 中创建两个 Path 的 Data 设置 ArcSegment 修改第二个

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实现圆形进度条的示例代码的文章就介绍到这了,更多相关WPF进度条内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号