这篇文章主要介绍了超炫酷的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">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>
在构建中发现,一开始在设定绑定时,写成
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控件的全部内容,希望对大家的学习有所帮助。
新闻热点
疑难解答