SL/WPF仿WIN8进度条

原文 http://www.cnblogs.com/kklldog/archive/2013/04/22/3036778.html

最近换到了win8,win8风格的进度条挺好玩的。可惜wpf上没有这个控件。那咱就自己来写一个吧。

用SL封装了个效果:

获取 Microsoft Silverlight

 

思路:这个过程可以分为3个阶段,最左边开始一个快速移动动画到中间位置,开始缓慢的做位移,然后再开始快速的飞到最右边,消失。且在第一个点缓动的时候,第二个点开始启动,依次类推,到最后一个点飞到最右边的时候,再启动第一个点。如此循环。

XAML:主要是定义4个点,以及每个点的动画。

复制代码
< UserControl  x:Class ="Win8ProcessBar.CtlWin8ProcessBar"
             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
="300"  d:DesignWidth ="300"  Height ="20"  Loaded ="UserControl_Loaded"    Initialized ="CtlWin8ProcessBar_OnInitialized" >

     < Canvas >
         < Ellipse  x:Name ="el"  Width ="6"  Height ="6"  Fill ="Black"  Canvas.Top ="7"  Canvas.Left ="0"  Opacity ="0" >
             < Ellipse.Resources >
                 < Storyboard  x:Key ="sbLeft"  Storyboard.TargetProperty ="(Canvas.Left)"  Storyboard.TargetName ="el" >
                     < DoubleAnimation  From =" {Binding  Path=LeftFrom, Mode=OneWay} "   To =" { Binding Path=LeftTo, Mode=OneWay} "   Duration ="0:0:0.25" >
                     </ DoubleAnimation >
                 </ Storyboard >
                 < Storyboard  x:Key ="sbSlow"  Storyboard.TargetProperty ="(Canvas.Left)"  Storyboard.TargetName ="el" >
                     < DoubleAnimation   From =" {Binding  Path=SlowFrom, Mode=OneWay} "   To =" { Binding Path=SlowTo, Mode=OneWay} "     Duration ="0:0:1" >
                     </ DoubleAnimation >
                 </ Storyboard >
                 < Storyboard  x:Key ="sbRight"  Storyboard.TargetProperty ="(Canvas.Left)"  Storyboard.TargetName ="el" >
                     < DoubleAnimation  From =" {Binding  Path=RightFrom, Mode=OneWay} "   To =" { Binding Path=RightTo, Mode=OneWay} "     Duration ="0:0:0.25" >
                     </ DoubleAnimation >
                 </ Storyboard >
             </ Ellipse.Resources >
         </ Ellipse >

         < Ellipse  x:Name ="el1"  Width ="6"  Height ="6"  Fill ="Black"  Canvas.Top ="7"  Canvas.Left ="0"  Opacity ="0" >
             < Ellipse.Resources >
                 < Storyboard  x:Key ="sbLeft1"  Storyboard.TargetProperty ="(Canvas.Left)"  Storyboard.TargetName ="el1" >
                     < DoubleAnimation    From =" {Binding  Path=LeftFrom, Mode=OneWay} "   To =" { Binding Path=LeftTo, Mode=OneWay} "   Duration ="0:0:0.25" >
                     </ DoubleAnimation >
                 </ Storyboard >
                 < Storyboard  x:Key ="sbSlow1"  Storyboard.TargetProperty ="(Canvas.Left)"  Storyboard.TargetName ="el1" >
                     < DoubleAnimation   From =" {Binding  Path=SlowFrom, Mode=OneWay} "   To =" { Binding Path=SlowTo, Mode=OneWay} "      Duration ="0:0:1" >
                     </ DoubleAnimation >
                 </ Storyboard >
                 < Storyboard  x:Key ="sbRight1"  Storyboard.TargetProperty ="(Canvas.Left)"  Storyboard.TargetName ="el1" >
                     < DoubleAnimation   From =" {Binding  Path=RightFrom, Mode=OneWay} "   To =" { Binding Path=RightTo, Mode=OneWay} "   Duration ="0:0:0.25" >
                     </ DoubleAnimation >
                 </ Storyboard >
             </ Ellipse.Resources >
         </ Ellipse >
===========================================这里省略2个点的定义==================================================
     </ Canvas >
复制代码

</UserControl> 

cs:

复制代码
// 作者:       minjie.zhou
//  创建时间:   2013/4/21 23:51:59

namespace Win8ProcessBar
{
     ///   <summary>
    
///  UProgressBar.xaml 的交互逻辑
    
///   </summary>
     public  partial  class CtlWin8ProcessBar : UserControl, INotifyPropertyChanged
    {
         public CtlWin8ProcessBar()
        {
            InitializeComponent();
        }

         private  void UserControl_Loaded( object sender, RoutedEventArgs e)
        {
             if ( double.IsNaN(Width)) // 默认为400的宽度
            {
                Width =  400;
            }
            LeftFrom =  0;
            LeftTo = Width /  2 - (Width / 7) /  2;
            SlowFrom = LeftTo;
            SlowTo = LeftTo + (Width /  7);
            RightFrom = SlowTo;
            RightTo = Width;

            Start();
        }

         #region 属性
         private  double _leftFrom;
         ///   <summary>
        
///  左边第一个起点
        
///   </summary>
         public  double LeftFrom
        {
             get {  return _leftFrom; }
             set
            {
                _leftFrom = value;
                 if ( this.PropertyChanged !=  null)
                {
                    NotifyPropertyChanged( " LeftFrom ");
                }
            }
        }

         private  double _leftTo;
         ///   <summary>
        
///  第一个终点
        
///   </summary>
         public  double LeftTo
        {
             get
            {
                 return _leftTo;
            }
             set
            {
                _leftTo = value;
                 if ( this.PropertyChanged !=  null)
                {
                    NotifyPropertyChanged( " LeftTo ");
                }
            }
        }

         private  double _slowFrom;
         ///   <summary>
        
///  缓动起点
        
///   </summary>
         public  double SlowFrom
        {
             get
            {
                 return _slowFrom;
            }
             set
            {
                _slowFrom = value;
                 if ( this.PropertyChanged !=  null)
                {
                    NotifyPropertyChanged( " SlowFrom ");
                }
            }
        }

         private  double _slowTo;
         ///   <summary>
        
///  缓动终点
        
///   </summary>
         public  double SlowTo
        {
             get
            { 
                 return _slowTo;
            }
             set
            {
                _slowTo = value;
                 if ( this.PropertyChanged !=  null)
                {
                    NotifyPropertyChanged( " SlowTo ");
                }
            }
        }

         private  double _rightFrom;
         ///   <summary>
        
///  右边起点
        
///   </summary>
         public  double RightFrom
        {
             get
            {
                 return _rightFrom;
            }
             set
            {
                _rightFrom = value;
                 if ( this.PropertyChanged !=  null)
                {
                    NotifyPropertyChanged( " RightFrom ");
                }
            }
        }

         private  double _rightTo;
         ///   <summary>
        
///  右边终点
        
///   </summary>
         public  double RightTo
        {
             get
            {
                 return _rightTo;
            }
             set
            {
                _rightTo = value;
                 if ( this.PropertyChanged !=  null)
                {
                    NotifyPropertyChanged( " RightTo ");
                }
            }
        }
         #endregion

         private  void CtlWin8ProcessBar_OnInitialized( object sender, EventArgs e)
        {
             this.DataContext =  this;

             this.el.Opacity =  0;
             this.el1.Opacity =  0;
             this.el2.Opacity =  0;
             this.el3.Opacity =  0;

             var sbLeft =  this.el.FindResource( " sbLeft "as Storyboard;
             var sbSlow =  this.el.FindResource( " sbSlow "as Storyboard;
             var sbRight =  this.el.FindResource( " sbRight "as Storyboard;

             var sbLeft1 =  this.el1.FindResource( " sbLeft1 "as Storyboard;
             var sbSlow1 =  this.el1.FindResource( " sbSlow1 "as Storyboard;
             var sbRight1 =  this.el1.FindResource( " sbRight1 "as Storyboard;

             var sbLeft2 =  this.el2.FindResource( " sbLeft2 "as Storyboard;
             var sbSlow2 =  this.el2.FindResource( " sbSlow2 "as Storyboard;
             var sbRight2 =  this.el2.FindResource( " sbRight2 "as Storyboard;

             var sbLeft3 =  this.el3.FindResource( " sbLeft3 "as Storyboard;
             var sbSlow3 =  this.el3.FindResource( " sbSlow3 "as Storyboard;
             var sbRight3 =  this.el3.FindResource( " sbRight3 "as Storyboard;

             // 第一个点第一个动画结束后开启缓动,第二个点启动
            sbLeft.Completed += (a, b) =>
                {
                    sbSlow.Begin();
                    el1.Opacity =  1;
                    sbLeft1.Begin();
                };
             // 第一个点缓动结束,右边动画启动
            sbSlow.Completed += (a, b) => sbRight.Begin();
            sbRight.Completed += (a, b) => el.Opacity =  0;
             // 以下类推
            sbLeft1.Completed += (a, b) =>
            {
                sbSlow1.Begin();
                el2.Opacity =  1;
                sbLeft2.Begin();
            };
            sbSlow1.Completed += (a, b) => sbRight1.Begin();
            sbRight1.Completed += (a, b) => el1.Opacity =  0;

            sbLeft2.Completed += (a, b) =>
            {
                sbSlow2.Begin();
                el3.Opacity =  1;
                sbLeft3.Begin();
            };
            sbSlow2.Completed += (a, b) => sbRight2.Begin();
            sbRight2.Completed += (a, b) => el2.Opacity =  0;

            sbLeft3.Completed += (a, b) => sbSlow3.Begin();
            sbSlow3.Completed += (a, b) => sbRight3.Begin();
             // 最后一个点动画结束,第一个点重启 如此循环
            sbRight3.Completed += (a, b) =>
            {
                el3.Opacity =  0;
                el.Opacity =  1;
                sbLeft.Begin();
            };
        }
      
         public  void Start()
        {
             var sb =  this.el.FindResource( " sbLeft "as Storyboard;
             this.el.Opacity =  1;
             if (sb !=  null)
                sb.Begin();
        }
         public  event PropertyChangedEventHandler PropertyChanged;

         private  void NotifyPropertyChanged(String propertyName =  "")
        {
             if (PropertyChanged !=  null)
            {
                PropertyChanged( thisnew PropertyChangedEventArgs(propertyName));
            }
        }
    }
复制代码

} 

重点:

 Sotryboard在sl/WPF里面做动画的时候有很大的作用。配合DoubleAnimation可以在一段时间内改变某个对象的double型属性。比如透明值在1秒内1到0。上面例子就是做了一个在一段时间内Canvas.Left属性从0到最右边的动画。配合ColorAnimation可以在2种颜色之间做渐变。

你可能感兴趣的:(win8)