網站首頁 編程語言 正文
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
?代碼如下:
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>
效果圖
原文鏈接:https://mp.weixin.qq.com/s/1ql9MCQqK2TfKGIoBtYXVw
相關推薦
- 2022-06-17 Go語言HttpRouter路由使用方法詳解_Golang
- 2022-11-02 Android?Studio模擬器運行apk文件_Android
- 2022-06-24 淺談React?中的淺比較是如何工作的_React
- 2022-12-23 loadavg數據異常引發問題起源分析_Android
- 2022-05-28 C++實現簡單的學生成績管理系統_C 語言
- 2021-12-19 C語言?八大排序算法的過程圖解及實現代碼_C 語言
- 2022-07-10 fastmock使用-只能模擬get請求
- 2022-08-23 一文教會你調整Matplotlib子圖的大小_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支