在設計界面時,有時會遇到進度條,本次講解WPF如何設計自定義的繞圈進度條,直接上代碼:
1、控件界面
01
<UserControl x:Class="ProgressBarControl"
02
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
03
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
04
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
05
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
06
mc:Ignorable="d" d:DesignHeight="200" d:DesignWidth="300"
07
Background="Gray" Loaded="ProgressBarControl_OnLoaded">
08
09
<Grid>
10
<Grid.Resources>
11
<Style TargetType="Ellipse">
12
<Setter Property="Height" Value="{Binding EclipseSize}"></Setter>
13
<Setter Property="Width" Value="{Binding EclipseSize}"></Setter>
14
<Setter Property="Stretch" Value="Fill"></Setter>
15
16
17
18
19
21
24
28
29
39
40
41
42
43
2、控件後臺邏輯:
控件後臺:
001
///
002
/// 進度條
003
///
004
public partial class ProgressBarControl : UserControl
005
{
006
//集成到按指定時間間隔和指定優先級處理的 System.Windows.Threading.Dispatcher 隊列中的計時器。
007
private DispatcherTimer animationTimer;
008
private ProgressBarDataModel _dataModel;
009
private int index = 0;
010
#region 構造方法與加載
011
///
012
/// 構造方法
013
///
014
public ProgressBarControl()
015
{
016
InitializeComponent();
017
018
}
019
///
020
/// 加載後刷新
021
///
022
///
023
///
024
private void ProgressBarControl_OnLoaded(object sender, RoutedEventArgs e)
025
{
026
animationTimer = new DispatcherTimer(DispatcherPriority.ContextIdle, Dispatcher);
027
//指定時間間隔
028
animationTimer.Interval = new TimeSpan(0, 0, 0, 0, TimeSpan);
029
if (EllipseCount < 1)
030
{
031
EllipseCount = 12;
032
}
033
for (int i = 0; i < EllipseCount; i++)
034
{
035
ProgressBarCanvas.Children.Add(new Ellipse());
036
}
037
var dataModel = new ProgressBarDataModel()
038
{
039
CanvasSize = CanvasSize,
040
EclipseSize = EllipseSize
041
};
042
_dataModel = dataModel;
043
this.DataContext = dataModel;
044
}
045
#endregion
046
047
#region 屬性
048
///
049
/// 獲取或設置圓圈數量
050
/// 默認12
051
///
052
public double EllipseCount
053
{
054
get { return (double)GetValue(EllipseCountProperty); }
055
set { SetValue(EllipseCountProperty, value); }
056
}
057
public static readonly DependencyProperty EllipseCountProperty =
058
DependencyProperty.Register("EllipseCount", typeof(double), typeof(ProgressBarControl),
059
new FrameworkPropertyMetadata(10.0, FrameworkPropertyMetadataOptions.AffectsRender));
060
061
///
062
/// 獲取或設置圓圈大小
063
/// 默認10
064
///
065
public double EllipseSize
066
{
067
get { return (double)GetValue(EllipseSizeProperty); }
068
set { SetValue(EllipseSizeProperty, value); }
069
}
070
public static readonly DependencyProperty EllipseSizeProperty =
071
DependencyProperty.Register("EllipseSize", typeof(double), typeof(ProgressBarControl),
072
new FrameworkPropertyMetadata(10.0, FrameworkPropertyMetadataOptions.AffectsRender));
073
074
///
075
/// 獲取或設置面板大小
076
/// 默認80
077
///
078
public double CanvasSize
079
{
080
get { return (double)GetValue(CanvasSizeProperty); }
081
set { SetValue(CanvasSizeProperty, value); }
082
}
083
public static readonly DependencyProperty CanvasSizeProperty =
084
DependencyProperty.Register("CanvasSize", typeof(double), typeof(ProgressBarControl),
085
new FrameworkPropertyMetadata(80.0, FrameworkPropertyMetadataOptions.AffectsRender));
086
087
///
088
/// 獲取或設置每次旋轉角度
089
/// 默認10.0
090
///
091
public double StepAngle
092
{
093
get { return (double)GetValue(StepAngleProperty); }
094
set { SetValue(StepAngleProperty, value); }
095
}
096
097
public static readonly DependencyProperty StepAngleProperty =
098
DependencyProperty.Register("StepAngle", typeof(double), typeof(ProgressBarControl),
099
new FrameworkPropertyMetadata(10.0, FrameworkPropertyMetadataOptions.AffectsRender));
100
///
101
/// 獲取或設置每次旋轉間隔時間(毫秒)
102
/// 默認100毫秒
103
///
104
public int TimeSpan
105
{
106
get { return (int)GetValue(TimeSpanProperty); }
107
set { SetValue(TimeSpanProperty, value); }
108
}
109
public static readonly DependencyProperty TimeSpanProperty =
110
DependencyProperty.Register("TimeSpan", typeof(int), typeof(ProgressBarControl),
111
new FrameworkPropertyMetadata(100, FrameworkPropertyMetadataOptions.AffectsRender));
112
113
#endregion
114
115
#region 方法
116
///
117
/// Canvas加載
118
///
119
///
120
///
121
private void HandleLoaded(object sender, RoutedEventArgs e)
122
{
123
//設置設置圓的位置和旋轉角度
124
SetEclipsePosition(_dataModel);
125
//DesignerProperties 提供用於與設計器進行通信的附加屬性。
126
if (!DesignerProperties.GetIsInDesignMode(this))
127
{
128
if (this.Visibility == System.Windows.Visibility.Visible)
129
{
130
//超過計時器間隔時發生。
131
animationTimer.Tick += HandleAnimationTick;
132
animationTimer.Start();
133
}
134
}
135
}
136
137
///
138
/// 設置圓的位置和旋轉角度
139
///
140
private void SetEclipsePosition(ProgressBarDataModel dataModel)
141
{
142
//圓周長就是:C = π * d 或者C=2*π*r(其中d是圓的直徑,r是圓的半徑)
143
double r =dataModel.R;
144
145
var children=ProgressBarCanvas.Children;
146
int count = children.Count;
147
double step = (Math.PI * 2) / count;
148
149
//根據圓中正弦、餘弦計算距離
150
int index = 0;
151
foreach (var element in children)
152
{
153
var ellipse = element as Ellipse;
154
//透明度
155
var opacity = Convert.ToDouble(index)/(count - 1);
156
ellipse.SetValue(UIElement.OpacityProperty, opacity<0.05?0.05:opacity);
157
//距離
158
double left = r + Math.Sin(step*index)*r;
159
ellipse.SetValue(Canvas.LeftProperty,left);
160
double top = r - Math.Cos(step*index)*r;
161
ellipse.SetValue(Canvas.TopProperty, top);
162
163
index++;
164
}
165
}
166
167
///
168
/// Canvas卸載時
169
///
170
///
171
///
172
private void HandleUnloaded(object sender, RoutedEventArgs e)
173
{
174
animationTimer.Stop();
175
//除去委託
176
animationTimer.Tick -= HandleAnimationTick;
177
}
178
179
///
180
/// 超過計時器間隔時發生。
181
///
182
///
183
///
184
private void HandleAnimationTick(object sender, EventArgs e)
185
{
186
//設置旋轉角度
187
SpinnerRotate.Angle = (SpinnerRotate.Angle + StepAngle) % 360;
188
}
189
#endregion
190
}
數據Model類:
01
///
02
/// 進度條Model類
03
///
04
public class ProgressBarDataModel
05
{
06
public double EclipseSize { get; set; }
07
public double CanvasSize { get; set; }
08
public double ViewBoxSize
09
{
10
get
11
{
12
double length = Convert.ToDouble(CanvasSize) - Convert.ToDouble(EclipseSize);
13
return length;
14
}
15
}
16
public double EclipseLeftLength
17
{
18
get
19
{
20
double length = Convert.ToDouble(CanvasSize) / 2;
21
return length;
22
}
23
}
24
public double R
25
{
26
get
27
{
28
double length = (Convert.ToDouble(CanvasSize) - Convert.ToDouble(EclipseSize)) / 2;
29
return length;
30
}
31
}
32
}
3、取用控件
1
本文原創自news.mkq.online