当前位置: 移动技术网 > IT编程>开发语言>.net > WPF实现转圈进度条效果

WPF实现转圈进度条效果

2018年08月05日  | 移动技术网IT编程  | 我要评论

盾憩岛,网络安全概念股,快递100

在设计界面时,有时会遇到进度条,本次讲解wpf如何设计自定义的绕圈进度条,直接上代码:

 

 1、控件界面

<usercontrol x:class="progressbarcontrol" 
       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"
       mc:ignorable="d" d:designheight="200" d:designwidth="300"
       background="gray" loaded="progressbarcontrol_onloaded">

  <grid>
    <grid.resources>
      <style targettype="ellipse">
        <setter property="height" value="{binding eclipsesize}"></setter>
        <setter property="width" value="{binding eclipsesize}"></setter>
        <setter property="stretch" value="fill"></setter>
        <!--设置圆的颜色-->
        <setter property="fill" value="white"></setter>
      </style>
    </grid.resources>
    <stackpanel  horizontalalignment="center" 
      verticalalignment="center">
      <viewbox width="{binding viewboxsize}" height="{binding viewboxsize}" 
      horizontalalignment="center" 
      verticalalignment="center">
        <grid x:name="layoutroot"  
        background="transparent" 
        horizontalalignment="center" 
        verticalalignment="center">
          <!--此处有canvas的加载和卸载事件-->
          <canvas x:name="progressbarcanvas" rendertransformorigin="0.5,0.5" 
          horizontalalignment="center" 
          verticalalignment="center" width="{binding canvassize}" 
          height="{binding canvassize}" loaded="handleloaded" 
          unloaded="handleunloaded" >
            <!--画圆-->            
            <canvas.rendertransform>
              <rotatetransform x:name="spinnerrotate" angle="0" />
            </canvas.rendertransform>
          </canvas>
        </grid>
      </viewbox>
    </stackpanel>
  </grid>
</usercontrol> 

2、控件后台逻辑:

 控件后台:

/// <summary>
  /// 进度条
  /// </summary>
  public partial class progressbarcontrol : usercontrol
  {
    //集成到按指定时间间隔和指定优先级处理的 system.windows.threading.dispatcher 队列中的计时器。
    private dispatchertimer animationtimer;
    private progressbardatamodel _datamodel;
    private int index = 0;
    #region 构造方法与加载
    /// <summary>
    /// 构造方法
    /// </summary>
    public progressbarcontrol()
    {
      initializecomponent();
      
    }
    /// <summary>
    /// 加载后刷新
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void progressbarcontrol_onloaded(object sender, routedeventargs e)
    {
      animationtimer = new dispatchertimer(dispatcherpriority.contextidle, dispatcher);
      //指定时间间隔
      animationtimer.interval = new timespan(0, 0, 0, 0, timespan);
      if (ellipsecount < 1)
      {
        ellipsecount = 12;
      }
      for (int i = 0; i < ellipsecount; i++)
      {
        progressbarcanvas.children.add(new ellipse());
      }
      var datamodel = new progressbardatamodel()
      {
        canvassize = canvassize,
        eclipsesize = ellipsesize
      };
      _datamodel = datamodel;
      this.datacontext = datamodel;
    }
    #endregion

    #region 属性
    /// <summary>
    /// 获取或设置圆圈数量
    /// 默认12
    /// </summary>
    public double ellipsecount
    {
      get { return (double)getvalue(ellipsecountproperty); }
      set { setvalue(ellipsecountproperty, value); }
    }
    public static readonly dependencyproperty ellipsecountproperty =
      dependencyproperty.register("ellipsecount", typeof(double), typeof(progressbarcontrol),
      new frameworkpropertymetadata(10.0, frameworkpropertymetadataoptions.affectsrender));

    /// <summary>
    /// 获取或设置圆圈大小
    /// 默认10
    /// </summary>
    public double ellipsesize
    {
      get { return (double)getvalue(ellipsesizeproperty); }
      set { setvalue(ellipsesizeproperty, value); }
    }
    public static readonly dependencyproperty ellipsesizeproperty =
      dependencyproperty.register("ellipsesize", typeof(double), typeof(progressbarcontrol),
      new frameworkpropertymetadata(10.0, frameworkpropertymetadataoptions.affectsrender));

    /// <summary>
    /// 获取或设置面板大小
    /// 默认80
    /// </summary>
    public double canvassize
    {
      get { return (double)getvalue(canvassizeproperty); }
      set { setvalue(canvassizeproperty, value); }
    }
    public static readonly dependencyproperty canvassizeproperty =
      dependencyproperty.register("canvassize", typeof(double), typeof(progressbarcontrol),
      new frameworkpropertymetadata(80.0, frameworkpropertymetadataoptions.affectsrender));

    /// <summary>
    /// 获取或设置每次旋转角度
    /// 默认10.0
    /// </summary>
    public double stepangle
    {
      get { return (double)getvalue(stepangleproperty); }
      set { setvalue(stepangleproperty, value); }
    }

    public static readonly dependencyproperty stepangleproperty =
      dependencyproperty.register("stepangle", typeof(double), typeof(progressbarcontrol),
      new frameworkpropertymetadata(10.0, frameworkpropertymetadataoptions.affectsrender));
    /// <summary>
    /// 获取或设置每次旋转间隔时间(毫秒)
    /// 默认100毫秒
    /// </summary>
    public int timespan
    {
      get { return (int)getvalue(timespanproperty); }
      set { setvalue(timespanproperty, value); }
    }
    public static readonly dependencyproperty timespanproperty =
      dependencyproperty.register("timespan", typeof(int), typeof(progressbarcontrol),
      new frameworkpropertymetadata(100, frameworkpropertymetadataoptions.affectsrender));
    
    #endregion

    #region 方法
    /// <summary>
    /// canvas加载
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void handleloaded(object sender, routedeventargs e)
    {
      //设置设置圆的位置和旋转角度
      seteclipseposition(_datamodel);
      //designerproperties  提供用于与设计器进行通信的附加属性。
      if (!designerproperties.getisindesignmode(this))
      {
        if (this.visibility == system.windows.visibility.visible)
        {
          //超过计时器间隔时发生。
          animationtimer.tick += handleanimationtick;
          animationtimer.start();
        }
      }
    }

    /// <summary>
    /// 设置圆的位置和旋转角度
    /// </summary>
    private void seteclipseposition(progressbardatamodel datamodel)
    {
      //圆周长就是:c = π * d 或者c=2*π*r(其中d是圆的直径,r是圆的半径)
      double r =datamodel.r;

      var children=progressbarcanvas.children;
      int count = children.count;
      double step = (math.pi * 2) / count;

      //根据圆中正弦、余弦计算距离
      int index = 0;
      foreach (var element in children)
      {
        var ellipse = element as ellipse;
        //透明度
        var opacity = convert.todouble(index)/(count - 1);
        ellipse.setvalue(uielement.opacityproperty, opacity<0.05?0.05:opacity);
        //距离
        double left = r + math.sin(step*index)*r;
        ellipse.setvalue(canvas.leftproperty,left);
        double top = r - math.cos(step*index)*r;
        ellipse.setvalue(canvas.topproperty, top);

        index++;
      }
    }

    /// <summary>
    /// canvas卸载时
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void handleunloaded(object sender, routedeventargs e)
    {
      animationtimer.stop();
      //除去委托
      animationtimer.tick -= handleanimationtick;
    }

    /// <summary>
    /// 超过计时器间隔时发生。
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void handleanimationtick(object sender, eventargs e)
    {
      //设置旋转角度
      spinnerrotate.angle = (spinnerrotate.angle + stepangle) % 360;
    }
    #endregion
}

数据model类:

/// <summary>
  /// 进度条model类
  /// </summary>
  public class progressbardatamodel
  {
    public double eclipsesize { get; set; }
    public double canvassize { get; set; }
    public double viewboxsize
    {
      get
      {
        double length = convert.todouble(canvassize) - convert.todouble(eclipsesize);
        return length;
      }
    }
    public double eclipseleftlength
    {
      get
      {
        double length = convert.todouble(canvassize) / 2;
        return length;
      }
    }
    public double r
    {
      get
      {
        double length = (convert.todouble(canvassize) - convert.todouble(eclipsesize)) / 2;
        return length;
      }
    }
}

3、取用控件

<control:progressbarcontrol canvassize="100" ellipsecount="10" ellipsesize="10" stepangle="36" timespan="60"/>

 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网