超炫酷的WPF實現(xiàn)Loading控件效果
Win8系統(tǒng)的Loading效果還是很不錯的,網(wǎng)上也有人用CSS3等技術實現(xiàn),研究了一下,并打算用WPF自定義一個Loading控件實現(xiàn)類似的效果,并可以讓用戶對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">00:00:00.000</system:TimeSpan> <system:TimeSpan x:Key = "StoryBoardBeginTimeP1">00:00:00.100</system:TimeSpan> <system:TimeSpan x:Key = "StoryBoardBeginTimeP2">00:00:00.200</system:TimeSpan> <system:TimeSpan x:Key = "StoryBoardBeginTimeP3">00:00:00.300</system:TimeSpan> <system:TimeSpan x:Key = "StoryBoardBeginTimeP4">00:00:00.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">00:00:00.000</system:TimeSpan> <Duration x:Key = "ParticleDuration1">00:00:00.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">00:00:00.751</system:TimeSpan> <Duration x:Key = "ParticleDuration2">00:00:00.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">00:00:00.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>
在構建中發(fā)現(xiàn),一開始在設定綁定時,寫成<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 操作,然后執(zhí)行步驟 2 以在 XAML 文件中使用此自定義控件。 /// /// 步驟 1a) 在當前項目中存在的 XAML 文件中使用該自定義控件。 /// 將此 XmlNamespace 特性添加到要使用該特性的標記文件的根 /// 元素中: /// /// xmlns:MyNamespace="clr-namespace:WpfControlLibraryDemo" /// /// /// 步驟 1b) 在其他項目中存在的 XAML 文件中使用該自定義控件。 /// 將此 XmlNamespace 特性添加到要使用該特性的標記文件的根 /// 元素中: /// /// xmlns:MyNamespace="clr-namespace:WpfControlLibraryDemo;assembly=WpfControlLibraryDemo" /// /// 您還需要添加一個從 XAML 文件所在的項目到此項目的項目引用, /// 并重新生成以避免編譯錯誤: /// /// 在解決方案資源管理器中右擊目標項目,然后依次單擊 /// “添加引用”->“項目”->[瀏覽查找并選擇此項目] /// /// /// 步驟 2) /// 繼續(xù)操作并在 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為控件初始化默認值 } //屬性變更回調函數(shù) 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實現(xiàn)炫酷Loading控件的全部內容,希望對大家的學習有所幫助。
相關文章
C#與SQL連接:GridView控件對數(shù)據(jù)庫的操作
GridView控件操作方面的知識,需要的朋友可以參考一下2013-02-02