WPF實(shí)現(xiàn)圓形進(jìn)度條的示例代碼
WPF 實(shí)現(xiàn)圓形進(jìn)度條
- 框架使用
.NET40
; Visual Studio 2019
;CircularProgressBar
繼承ProgressBar
,在XAML
中創(chuàng)建兩個(gè)Path
的Data
設(shè)置ArcSegment
修改第二個(gè)控件的Point
,設(shè)置StartPoint = new Point(Size.Width, 0)
設(shè)置起點(diǎn)。- 創(chuàng)建依賴屬性
Angle
作為修改ArcSegment
的Point
作為進(jìn)度條的圓的閉合。 - 當(dāng)進(jìn)度條
ValueChanged
時(shí)創(chuàng)建DoubleAnimation
動(dòng)畫,修改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="微信公眾號(hào):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>
效果圖
到此這篇關(guān)于WPF實(shí)現(xiàn)圓形進(jìn)度條的示例代碼的文章就介紹到這了,更多相關(guān)WPF進(jìn)度條內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#實(shí)現(xiàn)Excel轉(zhuǎn)PDF時(shí)設(shè)置內(nèi)容適應(yīng)頁面寬度
將Excel轉(zhuǎn)為PDF格式時(shí),通常情況下轉(zhuǎn)換出來的PDF頁面都是默認(rèn)的寬度大小。所以本文提供了C#實(shí)現(xiàn)Excel轉(zhuǎn)PDF時(shí)設(shè)置內(nèi)容適應(yīng)頁面寬度的示例代碼,需要的可以參考一下2022-04-04WinForm實(shí)現(xiàn)基于BindingSource的方法擴(kuò)展
這篇文章主要介紹了WinForm實(shí)現(xiàn)基于BindingSource的方法擴(kuò)展,需要的朋友可以參考下2014-08-08C#基礎(chǔ)知識(shí)之GetType與typeof的區(qū)別小結(jié)
在比較對(duì)象時(shí),需要了解他們的類型,才能決定他們的值是否能比較。所有的類都從System.Object中繼承了GetType()方法,常常與typeo()運(yùn)算符一起使用。這篇文章主要給大家介紹了關(guān)于C#基礎(chǔ)知識(shí)之GetType與typeof區(qū)別的相關(guān)資料,需要的朋友可以參考下2021-06-06DataGridView控件顯示行號(hào)的正確代碼及分析
今天要用到DataGridView,想給它動(dòng)態(tài)的顯示行號(hào)。于是在網(wǎng)上找了一下解決方法。結(jié)果發(fā)現(xiàn)了不少問題。然而就是這么一段有錯(cuò)的代碼,幾乎充斥著整個(gè)互聯(lián)網(wǎng),千篇一律的COPY,沒有一個(gè)人糾正2013-08-08WinForm實(shí)現(xiàn)移除控件某個(gè)事件的方法
這篇文章主要介紹了WinForm實(shí)現(xiàn)移除控件某個(gè)事件的方法,對(duì)C#初學(xué)者有一定的借鑒價(jià)值,需要的朋友可以參考下2014-08-08