WPF 圆形进度条(一):整体框架

时间:2016-04-10 16:10:35   收藏:0   阅读:2752

  看了浸水的WPF 实现圆形进度条这篇文章,突发灵感,决定自己做一个圆形进度条(用户控件),名为LoadingRing。

  首先,圆形进度条必定有一个Ellipse(这简直就是废话),所以需要一个Ellipse。

技术分享

  为了好看,我把它设为灰色并且半透明。

  接着需要填充部分的控件,开始我想用Ellipse,并用StrokeDashArray来填充的,但是后来发现使用StrokeDashArray就难以使用动画。折腾半天,还是在Blend使用Arc形状好了。Arc中的StartAngle指定弧线的起始处,以圆的最顶端为0°,EndAngle指定结束的度数。现在的代码如下:

1 <Ellipse Stroke="Gray" StrokeThickness="3" Opacity="0.6"/>
2 <ed:Arc ArcThickness="3" EndAngle="0" Margin="0" Stretch="None" Stroke="Transparent" StrokeThickness="0" StartAngle="0" Fill="#FF0071BC" x:Name="EllipseFill"/>

  还有一点细节,就是使用ed还要声明:

1 xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing"

  把EndAngle随便设个1~360之间的数(0就看不见了)来看看效果。

技术分享

  效果还挺令人满意。但有一个很重要的依赖性属性还没定义,给使用者设定进度,我把它的名设为Value。

 1 public static DependencyProperty ValueProperty;
 2 public byte Value
 3 {
 4     get { return (byte)GetValue(ValueProperty); }
 5     set { SetValue(ValueProperty, value); }
 6 }
 7 
 8 static LoadingRing()
 9 {
10     ValueProperty = DependencyProperty.Register("Value", typeof(byte), typeof(LoadingRing), new FrameworkPropertyMetadata((byte)0, new PropertyChangedCallback(OnValueChanged)));
11 }

  (有一个编程的细节就是初始值前要加byte的显示转换,因为数值默认为int。否则编译器会一直告诉你初始值错误,无法调用构造函数,却不知道哪里有错误。)

  和一个依赖项回调函数:

private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
  LoadingRing lr = (LoadingRing)d;
  if (lr.Value > 100) lr.Value = 100;
  if (lr.Value < 0) lr.Value = 0;
  lr.EllipseFill.EndAngle = lr.Value / 0.01 * 360;
}

   不显示进度多少,着急的你沉得住气吗?加一个TextBlock用作显示进度。XAML代码增加一行:

1 <TextBlock Foreground="White" FontSize="30" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,-40,0,0" x:Name="TValue" FontFamily="Segoe UI"><Run Text="0%"/></TextBlock>

  进度更新时也要有变化,在回调函数中添加一行:  

1 lr.TValue.Text = lr.Value.ToString() + "%";

  来看看效果。

技术分享

  感觉不错,但总觉得应该告诉别人你在干什么,加多一个TextBlock显示事件。XAML代码再增加一行:

1 <TextBlock Foreground="White" FontSize="17" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,-45" x:Name="TText" FontFamily="Segoe UI Light"><Run Text="Something to do…"/></TextBlock>

  还有另一个依赖项和回调函数:

 1 public static DependencyProperty TextProperty;
 2 public string Text
 3 {
 4   get { return (string)GetValue(TextProperty); }
 5   set { SetValue(TextProperty, value); }
 6 }
 7 
 8 static LoadingRing()
 9 { 
10   TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(LoadingRing), new FrameworkPropertyMetadata("Something to do…", new PropertyChangedCallback(OnTextChanged)));
11   ValueProperty = DependencyProperty.Register("Value", typeof(byte), typeof(LoadingRing), new FrameworkPropertyMetadata((byte)0, new PropertyChangedCallback(OnValueChanged)));
12 
13 }
14 
15 private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
16 {
17   LoadingRing lr = (LoadingRing)d;
18   lr.TText.Text = lr.Text;
19 }

   结果还挺好看:

技术分享

 

  可在进度变化时,填充区域的变化显得十分死板,直接跳到另一边。所以下一篇将会给它一点灵性,用一些动画使它变得流畅一些。

 

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!