好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

超炫酷的WPF实现Loading控件效果

win8系统的loading效果还是很不错的,网上也有人用css3等技术实现,研究了一下,并打算用wpf自定义一个loading控件实现类似的效果,并可以让用户对loading的颗粒(particle)背景颜色进行自定义,话不多说,直接上代码:

1、用vs2012新建一个wpf的用户控件库项目wpfcontrollibrarydemo,vs自动生成如下结构:

2、删除usercontrol1.xaml,并新建一个loading的customcontrol(不是usercontrol),如下图所示:

3、如果报错找不到loading类型,请编译,下面在generic.xaml主题文件中对loading的样式和内容进行定义(注意添加

?

xmlns:system = "clr-namespace:system;assembly=mscorlib" ),代码如下:

<resourcedictionary

  xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation"

  xmlns:x= "http://schemas.microsoft.com/winfx/2006/xaml"

  xmlns:system = "clr-namespace:system;assembly=mscorlib"

  xmlns:local= "clr-namespace:wpfcontrollibrarydemo" >

 

 

  <style targettype= "{x:type local:loading}" >

  <setter property= "template" >

   <setter.value>

   <controltemplate targettype= "{x:type local:loading}" >

    <border background= "{templatebinding background}"

     borderbrush= "{templatebinding borderbrush}"

     borderthickness= "{templatebinding borderthickness}" >

    <grid width = "50" height = "50" >

     <grid.resources>

     <!-- value converters -->

    

     <!-- particle styling ,must to has relativesource -->

     <solidcolorbrush x:key = "particlecolor" color = "{binding path=fillcolor,relativesource={relativesource templatedparent}}" />

     <solidcolorbrush x:key = "particlebackgroundcolor" color = "transparent" />

     <system: double x:key = "particleopacity" >1</system: double >

     <system: double x:key = "particleradius" >5</system: double >

 

     <system: double x:key = "startingpointx" >0</system: double >

     <system: double x:key = "startingpointy" >-20</system: double >

 

     <system: double x:key = "rotationpointx" >0.5</system: double >

     <system: double x:key = "rotationpointy" >0.5</system: double >

 

     <!-- storyboard -->

     <system:timespan x:key = "storyboardbegintimep0" >0.000</system:timespan>

     <system:timespan x:key = "storyboardbegintimep1" >0.100</system:timespan>

     <system:timespan x:key = "storyboardbegintimep2" >0.200</system:timespan>

     <system:timespan x:key = "storyboardbegintimep3" >0.300</system:timespan>

     <system:timespan x:key = "storyboardbegintimep4" >0.400</system:timespan>

     <duration x:key = "storyboardduration" >00:00:01.800</duration>

 

     <!-- particle origin angles -->

     <system: double x:key = "particleoriginanglep0" >0</system: double >

     <system: double x:key = "particleoriginanglep1" >-10</system: double >

     <system: double x:key = "particleoriginanglep2" >-20</system: double >

     <system: double x:key = "particleoriginanglep3" >-30</system: double >

     <system: double x:key = "particleoriginanglep4" >-40</system: double >

 

     <!-- particle position & timing 1 -->

     <system: double x:key = "particlebeginangle1" >0</system: double >

     <system: double x:key = "particleendangle1" >90</system: double >

     <system:timespan x:key = "particlebegintime1" >0.000</system:timespan>

     <duration x:key = "particleduration1" >0.750</duration>

 

     <!-- particle position & timing 2 -->

     <system: double x:key = "particlebeginangle2" >90</system: double >

     <system: double x:key = "particleendangle2" >270</system: double >

     <system:timespan x:key = "particlebegintime2" >0.751</system:timespan>

     <duration x:key = "particleduration2" >0.300</duration>

 

     <!-- particle position & timing 3 -->

     <system: double x:key = "particlebeginangle3" >270</system: double >

     <system: double x:key = "particleendangle3" >360</system: double >

     <system:timespan x:key = "particlebegintime3" >00:00:01.052</system:timespan>

     <duration x:key = "particleduration3" >0.750</duration>

 

     <style x:key = "ellipsestyle" targettype = "ellipse" >

      <setter property = "width" value = "{staticresource particleradius}" />

      <setter property = "height" value = "{staticresource particleradius}" />

      <setter property = "fill" value = "{staticresource particlecolor}" />

      <setter property = "rendertransformorigin" value = "0.5, 0.5" />

      <setter property = "opacity" value = "{staticresource particleopacity}" />

     </style>

     </grid.resources>

     <canvas width = "1" height = "1" margin= "0,0,0,0" >

     <canvas.triggers>

      <eventtrigger routedevent = "canvas.loaded" >

      <eventtrigger.actions>

       <beginstoryboard>

       <storyboard

    

     begintime = "{staticresource storyboardbegintimep0}"

     duration = "{staticresource storyboardduration}"

     repeatbehavior = "forever" >

        <doubleanimation

     storyboard.targetname = "p0"

     storyboard.targetproperty = "(uielement.rendertransform).(rotatetransform.angle)"

     from = "{staticresource particlebeginangle1}"

     to = "{staticresource particleendangle1}"

     begintime = "{staticresource particlebegintime1}"

     duration = "{staticresource particleduration1}" />

        <doubleanimation

     storyboard.targetname = "p0"

     storyboard.targetproperty = "(uielement.rendertransform).(rotatetransform.angle)"

     from = "{staticresource particlebeginangle2}"

     to = "{staticresource particleendangle2}"

     begintime = "{staticresource particlebegintime2}"

     duration = "{staticresource particleduration2}" />

        <doubleanimation

     storyboard.targetname = "p0"

     storyboard.targetproperty = "(uielement.rendertransform).(rotatetransform.angle)"

     from = "{staticresource particlebeginangle3}"

     to = "{staticresource particleendangle3}"

     begintime = "{staticresource particlebegintime3}"

     duration = "{staticresource particleduration3}" />

       </storyboard>

       </beginstoryboard>

       <beginstoryboard>

       <storyboard

    

     begintime = "{staticresource storyboardbegintimep1}"

     duration = "{staticresource storyboardduration}"

     repeatbehavior = "forever" >

 

        <doubleanimation

     storyboard.targetname = "p1"

     storyboard.targetproperty = "(uielement.rendertransform).(rotatetransform.angle)"

     from = "{staticresource particlebeginangle1}"

     to = "{staticresource particleendangle1}"

     begintime = "{staticresource particlebegintime1}"

     duration = "{staticresource particleduration1}" />

        <doubleanimation

     storyboard.targetname = "p1"

     storyboard.targetproperty = "(uielement.rendertransform).(rotatetransform.angle)"

     from = "{staticresource particlebeginangle2}"

     to = "{staticresource particleendangle2}"

     begintime = "{staticresource particlebegintime2}"

     duration = "{staticresource particleduration2}" />

        <doubleanimation

     storyboard.targetname = "p1"

     storyboard.targetproperty = "(uielement.rendertransform).(rotatetransform.angle)"

     from = "{staticresource particlebeginangle3}"

     to = "{staticresource particleendangle3}"

     begintime = "{staticresource particlebegintime3}"

     duration = "{staticresource particleduration3}" />

       </storyboard>

       </beginstoryboard>

       <beginstoryboard>

       <storyboard

    

     begintime = "{staticresource storyboardbegintimep2}"

     duration = "{staticresource storyboardduration}"

     repeatbehavior = "forever" >

 

        <doubleanimation

     storyboard.targetname = "p2"

     storyboard.targetproperty = "(uielement.rendertransform).(rotatetransform.angle)"

     from = "{staticresource particlebeginangle1}"

     to = "{staticresource particleendangle1}"

     begintime = "{staticresource particlebegintime1}"

     duration = "{staticresource particleduration1}" />

        <doubleanimation

     storyboard.targetname = "p2"

     storyboard.targetproperty = "(uielement.rendertransform).(rotatetransform.angle)"

     from = "{staticresource particlebeginangle2}"

     to = "{staticresource particleendangle2}"

     begintime = "{staticresource particlebegintime2}"

     duration = "{staticresource particleduration2}" />

        <doubleanimation

     storyboard.targetname = "p2"

     storyboard.targetproperty = "(uielement.rendertransform).(rotatetransform.angle)"

     from = "{staticresource particlebeginangle3}"

     to = "{staticresource particleendangle3}"

     begintime = "{staticresource particlebegintime3}"

     duration = "{staticresource particleduration3}" />

       </storyboard>

       </beginstoryboard>

 

       <beginstoryboard>

       <storyboard

    

     begintime = "{staticresource storyboardbegintimep3}"

     duration = "{staticresource storyboardduration}"

     repeatbehavior = "forever" >

 

        <doubleanimation

     storyboard.targetname = "p3"

     storyboard.targetproperty = "(uielement.rendertransform).(rotatetransform.angle)"

     from = "{staticresource particlebeginangle1}"

     to = "{staticresource particleendangle1}"

     begintime = "{staticresource particlebegintime1}"

     duration = "{staticresource particleduration1}" />

        <doubleanimation

     storyboard.targetname = "p3"

     storyboard.targetproperty = "(uielement.rendertransform).(rotatetransform.angle)"

     from = "{staticresource particlebeginangle2}"

     to = "{staticresource particleendangle2}"

     begintime = "{staticresource particlebegintime2}"

     duration = "{staticresource particleduration2}" />

        <doubleanimation

     storyboard.targetname = "p3"

     storyboard.targetproperty = "(uielement.rendertransform).(rotatetransform.angle)"

     from = "{staticresource particlebeginangle3}"

     to = "{staticresource particleendangle3}"

     begintime = "{staticresource particlebegintime3}"

     duration = "{staticresource particleduration3}" />

       </storyboard>

       </beginstoryboard>

 

       <beginstoryboard>

       <storyboard

    

     begintime = "{staticresource storyboardbegintimep4}"

     duration = "{staticresource storyboardduration}"

     repeatbehavior = "forever" >

 

        <doubleanimation

     storyboard.targetname = "p4"

     storyboard.targetproperty = "(uielement.rendertransform).(rotatetransform.angle)"

     from = "{staticresource particlebeginangle1}"

     to = "{staticresource particleendangle1}"

     begintime = "{staticresource particlebegintime1}"

     duration = "{staticresource particleduration1}" />

        <doubleanimation

     storyboard.targetname = "p4"

     storyboard.targetproperty = "(uielement.rendertransform).(rotatetransform.angle)"

     from = "{staticresource particlebeginangle2}"

     to = "{staticresource particleendangle2}"

     begintime = "{staticresource particlebegintime2}"

     duration = "{staticresource particleduration2}" />

        <doubleanimation

     storyboard.targetname = "p4"

     storyboard.targetproperty = "(uielement.rendertransform).(rotatetransform.angle)"

     from = "{staticresource particlebeginangle3}"

     to = "{staticresource particleendangle3}"

     begintime = "{staticresource particlebegintime3}"

     duration = "{staticresource particleduration3}" />

       </storyboard>

       </beginstoryboard>

      </eventtrigger.actions>

      </eventtrigger>

     </canvas.triggers>

     <border

   x:name = "p0"

   background = "{staticresource particlebackgroundcolor}"

   opacity = "{staticresource particleopacity}" >

      <border.rendertransform>

      <rotatetransform/>

      </border.rendertransform>

      <border.rendertransformorigin>

      <point x = "{staticresource rotationpointx}" y = "{staticresource rotationpointy}" />

      </border.rendertransformorigin>

      <ellipse style = "{staticresource ellipsestyle}" >

      <ellipse.rendertransform>

       <transformgroup>

       <translatetransform x = "{staticresource startingpointx}" y = "{staticresource startingpointy}" />

       <rotatetransform angle = "{staticresource particleoriginanglep0}" />

       </transformgroup>

      </ellipse.rendertransform>

      </ellipse>

     </border>

     <border

   x:name = "p1"

   background = "{staticresource particlebackgroundcolor}"

   opacity = "{staticresource particleopacity}" >

      <border.rendertransform>

      <rotatetransform/>

      </border.rendertransform>

      <border.rendertransformorigin>

      <point x = "{staticresource rotationpointx}" y = "{staticresource rotationpointy}" />

      </border.rendertransformorigin>

      <ellipse style = "{staticresource ellipsestyle}" >

      <ellipse.rendertransform>

       <transformgroup>

       <translatetransform x = "{staticresource startingpointx}" y = "{staticresource startingpointy}" />

       <rotatetransform angle = "{staticresource particleoriginanglep1}" />

       </transformgroup>

      </ellipse.rendertransform>

      </ellipse>

     </border>

     <border

   x:name = "p2"

   background = "{staticresource particlebackgroundcolor}"

   opacity = "{staticresource particleopacity}" >

      <border.rendertransform>

      <rotatetransform/>

      </border.rendertransform>

      <border.rendertransformorigin>

      <point x = "{staticresource rotationpointx}" y = "{staticresource rotationpointy}" />

      </border.rendertransformorigin>

      <ellipse style = "{staticresource ellipsestyle}" >

      <ellipse.rendertransform>

       <transformgroup>

       <translatetransform x = "{staticresource startingpointx}" y = "{staticresource startingpointy}" />

       <rotatetransform angle = "{staticresource particleoriginanglep2}" />

       </transformgroup>

      </ellipse.rendertransform>

      </ellipse>

     </border>

     <border

   x:name = "p3"

   background = "{staticresource particlebackgroundcolor}"

   opacity = "{staticresource particleopacity}" >

      <border.rendertransform>

      <rotatetransform/>

      </border.rendertransform>

      <border.rendertransformorigin>

      <point x = "{staticresource rotationpointx}" y = "{staticresource rotationpointy}" />

      </border.rendertransformorigin>

      <ellipse style = "{staticresource ellipsestyle}" >

      <ellipse.rendertransform>

       <transformgroup>

       <translatetransform x = "{staticresource startingpointx}" y = "{staticresource startingpointy}" />

       <rotatetransform angle = "{staticresource particleoriginanglep3}" />

       </transformgroup>

      </ellipse.rendertransform>

      </ellipse>

     </border>

     <border

   x:name = "p4"

   background = "{staticresource particlebackgroundcolor}"

   opacity = "{staticresource particleopacity}" >

      <border.rendertransform>

      <rotatetransform/>

      </border.rendertransform>

      <border.rendertransformorigin>

      <point x = "{staticresource rotationpointx}" y = "{staticresource rotationpointy}" />

      </border.rendertransformorigin>

      <ellipse style = "{staticresource ellipsestyle}" >

      <ellipse.rendertransform>

       <transformgroup>

       <translatetransform x = "{staticresource startingpointx}" y = "{staticresource startingpointy}" />

       <rotatetransform angle = "{staticresource particleoriginanglep4}" />

       </transformgroup>

      </ellipse.rendertransform>

      </ellipse>

     </border>

     </canvas>

    </grid>

 

 

 

    </border>

   </controltemplate>

   </setter.value>

  </setter>

  </style>

 

 

 

</resourcedictionary>

在构建中发现,一开始在设定绑定时,写成<solidcolorbrush x:key = "particlecolor" color = "{binding path=fillcolor}" />一直都无法绑定成功,后来查了资料,改成<solidcolorbrush x:key = "particlecolor" color = "{binding path=fillcolor,relativesource={relativesource templatedparent}}" /> 后成功。

4、编辑loading.cs文件,对自定义属性fillcolor和逻辑进行编码:

?

using system;

using system.collections.generic;

using system.linq;

using system.text;

using system.threading.tasks;

using system.windows;

using system.windows.controls;

using system.windows.data;

using system.windows.documents;

using system.windows.input;

using system.windows.media;

using system.windows.media.imaging;

using system.windows.navigation;

using system.windows.shapes;

 

namespace wpfcontrollibrarydemo

{

  using system.componentmodel;

  /// <summary>

  /// 按照步骤 1a 或 1b 操作,然后执行步骤 2 以在 xaml 文件中使用此自定义控件。

  ///

  /// 步骤 1a) 在当前项目中存在的 xaml 文件中使用该自定义控件。

  /// 将此 xmlnamespace 特性添加到要使用该特性的标记文件的根

  /// 元素中:

  ///

  /// xmlns:mynamespace="clr-namespace:wpfcontrollibrarydemo"

  ///

  ///

  /// 步骤 1b) 在其他项目中存在的 xaml 文件中使用该自定义控件。

  /// 将此 xmlnamespace 特性添加到要使用该特性的标记文件的根

  /// 元素中:

  ///

  /// xmlns:mynamespace="clr-namespace:wpfcontrollibrarydemo;assembly=wpfcontrollibrarydemo"

  ///

  /// 您还需要添加一个从 xaml 文件所在的项目到此项目的项目引用,

  /// 并重新生成以避免编译错误:

  ///

  /// 在解决方案资源管理器中右击目标项目,然后依次单击

  /// [添加引用]->[项目]->[浏览查找并选择此项目]

  ///

  ///

  /// 步骤 2)

  /// 继续操作并在 xaml 文件中使用控件。

  ///

  /// <mynamespace:loading/>

  ///

  /// </summary>

  public class loading : control

  {

  static loading()

  {

   //重载默认样式

   defaultstylekeyproperty.overridemetadata( typeof (loading), new frameworkpropertymetadata( typeof (loading)));

   //dependencyproperty 注册 fillcolor

   fillcolorproperty = dependencyproperty.register( "fillcolor" ,

   typeof (color),

   typeof (loading),

   new uipropertymetadata(colors.darkblue,

   new propertychangedcallback(onurichanged))

   );

   //colors.darkblue为控件初始化默认值

 

  }

  //属性变更回调函数

  private static void onurichanged(dependencyobject d, dependencypropertychangedeventargs e)

  {

   //border b = (border)d;

   //messagebox.show(e.newvalue.tostring());

 

  }

  #region 自定义fields

  // dependencyproperty属性定义 fillcolorproperty=fillcolor+property组成

  public static readonly dependencyproperty fillcolorproperty;

  #endregion

  //vs设计器属性支持

  [description( "背景色" ), category( "个性配置" ), defaultvalue( "#ff668899" )]

  public color fillcolor

  {

   //getvalue,setvalue为固定写法,此处一般不建议处理其他逻辑

   get { return (color)getvalue(fillcolorproperty); }

   set { setvalue(fillcolorproperty, value); }

  }

  }

}

 5、编译,如果无误后,可以添加wpf应用程序wpfapploadingtest进行测试(添加项目引用)。

打开mainwindow.xaml,将loading控件拖放到设计界面上,如下图所示:

 6、控件颜色修改,选中控件,在属性栏中进行配置即可:

 7.总结

可以看到wpf自定义控件还是比较容易的,但是难点在于ui的设计,如果需要做的美观,需要美工的参与,而且需要转换成xaml。

以上就是wpf实现炫酷loading控件的全部内容,希望对大家的学习有所帮助。

dy("nrwz");

查看更多关于超炫酷的WPF实现Loading控件效果的详细内容...

  阅读:76次