WPF UI开发教程自定义loading等待控件

92 篇文章 9 订阅
92 篇文章 24 订阅

在项目开发过程中总会遇到一个需求:Loading...正在加载中,这样一个需求作为加载的过渡效果。

控件主要原理以半径X,Y轴进行旋转,按照时钟原理画12个点,这里的RenderTransformOrigin="0.5,0.5"表示以图片的圆心为指定变换原点,每个点旋转角度从0到360度,每次以30度递增。

在控件加载事件中取透明值依赖属性进行时间段递增显示。

先显示loading等待控件效果

WPF UI开发教程自定义loading等待控件

控件样式代码:

<Style TargetType="{x:Type local:LoadingBox}">
        <!--<Setter Property="Height" Value="64"/>
        <Setter Property="Width" Value="64"/>-->
        <Setter Property="RadiusX" Value="4"/>
        <Setter Property="RadiusY" Value="4"/>
        <Setter Property="Foreground" Value="{DynamicResource Nb.Loading.Foreground}"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate>
                    <Grid Name ="loading" Visibility="Visible" Height="{TemplateBinding Height}" Width ="{TemplateBinding Width}" VerticalAlignment="{TemplateBinding VerticalAlignment}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}">
                        <Grid.Resources>
                            <DrawingBrush x:Key="brush" Stretch="None" AlignmentX ="Center" AlignmentY="Top">
                                <DrawingBrush.Drawing>
                                    <GeometryDrawing Brush ="{Binding RelativeSource={RelativeSource AncestorType=nb:LoadingBox},Path=Foreground}">
                                        <GeometryDrawing.Geometry>
                                            <EllipseGeometry RadiusX ="{Binding RelativeSource={RelativeSource AncestorType=nb:LoadingBox},Path=RadiusX}" 
                                                             RadiusY="{Binding RelativeSource={RelativeSource AncestorType=nb:LoadingBox},Path=RadiusY}"/>
                                        </GeometryDrawing.Geometry>
                                    </GeometryDrawing>
                                </DrawingBrush.Drawing>
                            </DrawingBrush>
                        </Grid.Resources>

                        <Rectangle x:Name="r01" Fill="{StaticResource brush}" Opacity ="{TemplateBinding Opacity}" RenderTransformOrigin="0.5,0.5">
                            <Rectangle.RenderTransform>
                                <RotateTransform Angle ="0"/>
                            </Rectangle.RenderTransform>
                        </Rectangle>
                        <Rectangle x:Name="r02" Fill="{StaticResource brush}" Opacity ="{TemplateBinding Opacity}" RenderTransformOrigin="0.5,0.5">
                            <Rectangle.RenderTransform>
                                <RotateTransform Angle ="30"/>
                            </Rectangle.RenderTransform>
                        </Rectangle>
                        <Rectangle x:Name="r03" Fill="{StaticResource brush}" Opacity ="{TemplateBinding Opacity}" RenderTransformOrigin="0.5,0.5">
                            <Rectangle.RenderTransform>
                                <RotateTransform Angle ="60"/>
                            </Rectangle.RenderTransform>
                        </Rectangle>
                        <Rectangle x:Name="r04" Fill="{StaticResource brush}" Opacity ="{TemplateBinding Opacity}" RenderTransformOrigin="0.5,0.5">
                            <Rectangle.RenderTransform>
                                <RotateTransform Angle ="90"/>
                            </Rectangle.RenderTransform>
                        </Rectangle>
                        <Rectangle x:Name="r05" Fill="{StaticResource brush}" Opacity ="{TemplateBinding Opacity}" RenderTransformOrigin="0.5,0.5">
                            <Rectangle.RenderTransform>
                                <RotateTransform Angle ="120"/>
                            </Rectangle.RenderTransform>
                        </Rectangle>
                        <Rectangle x:Name="r06" Fill="{StaticResource brush}" Opacity ="{TemplateBinding Opacity}" RenderTransformOrigin="0.5,0.5">
                            <Rectangle.RenderTransform>
                                <RotateTransform Angle ="150"/>
                            </Rectangle.RenderTransform>
                        </Rectangle>
                        <Rectangle x:Name="r07" Fill="{StaticResource brush}" Opacity ="{TemplateBinding Opacity}" RenderTransformOrigin="0.5,0.5">
                            <Rectangle.RenderTransform>
                                <RotateTransform Angle ="180"/>
                            </Rectangle.RenderTransform>
                        </Rectangle>
                        <Rectangle x:Name="r08" Fill="{StaticResource brush}" Opacity ="{TemplateBinding Opacity}" RenderTransformOrigin="0.5,0.5">
                            <Rectangle.RenderTransform>
                                <RotateTransform Angle ="210"/>
                            </Rectangle.RenderTransform>
                        </Rectangle>
                        <Rectangle x:Name="r09" Fill="{StaticResource brush}" Opacity ="{TemplateBinding Opacity}" RenderTransformOrigin="0.5,0.5">
                            <Rectangle.RenderTransform>
                                <RotateTransform Angle ="240"/>
                            </Rectangle.RenderTransform>
                        </Rectangle>
                        <Rectangle x:Name="r10" Fill="{StaticResource brush}" Opacity ="{TemplateBinding Opacity}" RenderTransformOrigin="0.5,0.5">
                            <Rectangle.RenderTransform>
                                <RotateTransform Angle ="270"/>
                            </Rectangle.RenderTransform>
                        </Rectangle>
                        <Rectangle x:Name="r11" Fill="{StaticResource brush}" Opacity ="{TemplateBinding Opacity}" RenderTransformOrigin="0.5,0.5">
                            <Rectangle.RenderTransform>
                                <RotateTransform Angle ="300"/>
                            </Rectangle.RenderTransform>
                        </Rectangle>
                        <Rectangle x:Name="r12" Fill="{StaticResource brush}" Opacity ="{TemplateBinding Opacity}" RenderTransformOrigin="0.5,0.5">
                            <Rectangle.RenderTransform>
                                <RotateTransform Angle ="330"/>
                            </Rectangle.RenderTransform>
                        </Rectangle>

                        <Grid.Triggers>
                            <EventTrigger RoutedEvent ="Grid.Loaded">
                                <BeginStoryboard>
                                    <Storyboard RepeatBehavior ="Forever">
                                        <DoubleAnimation Storyboard.TargetName ="r01" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime ="0:0:0.00000" To="0"/>
                                        <DoubleAnimation Storyboard.TargetName ="r02" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime ="0:0:0.08333" To="0"/>
                                        <DoubleAnimation Storyboard.TargetName ="r03" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime ="0:0:0.16666" To="0"/>
                                        <DoubleAnimation Storyboard.TargetName ="r04" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime ="0:0:0.24999" To="0"/>
                                        <DoubleAnimation Storyboard.TargetName ="r05" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime ="0:0:0.33332" To="0"/>
                                        <DoubleAnimation Storyboard.TargetName ="r06" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime ="0:0:0.41665" To="0"/>
                                        <DoubleAnimation Storyboard.TargetName ="r07" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime ="0:0:0.49998" To="0"/>
                                        <DoubleAnimation Storyboard.TargetName ="r08" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime ="0:0:0.58331" To="0"/>
                                        <DoubleAnimation Storyboard.TargetName ="r09" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime ="0:0:0.66664" To="0"/>
                                        <DoubleAnimation Storyboard.TargetName ="r10" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime ="0:0:0.74997" To="0"/>
                                        <DoubleAnimation Storyboard.TargetName ="r11" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime ="0:0:0.83330" To="0"/>
                                        <DoubleAnimation Storyboard.TargetName ="r12" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime ="0:0:0.91663" To="0"/>
                                    </Storyboard>
                                </BeginStoryboard>
                            </EventTrigger>
                        </Grid.Triggers>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

默认半径RadiusX,RadiusY是4

<Grid.Resources>
                            <DrawingBrush x:Key="brush" Stretch="None" AlignmentX ="Center" AlignmentY="Top">
                                <DrawingBrush.Drawing>
                                    <GeometryDrawing Brush ="{Binding RelativeSource={RelativeSource AncestorType=nb:LoadingBox},Path=Foreground}">
                                        <GeometryDrawing.Geometry>
                                            <EllipseGeometry RadiusX ="{Binding RelativeSource={RelativeSource AncestorType=nb:LoadingBox},Path=RadiusX}" 
                                                             RadiusY="{Binding RelativeSource={RelativeSource AncestorType=nb:LoadingBox},Path=RadiusY}"/>
                                        </GeometryDrawing.Geometry>
                                    </GeometryDrawing>
                                </DrawingBrush.Drawing>
                            </DrawingBrush>
                        </Grid.Resources>

重写Grid资源样式,用DrawingBrush来绘制区域,EllipseGeometry 以半径RadiusX,RadiusY矢量图型绘制圆型。

public class LoadingBox : Control
    {

        static LoadingBox()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(LoadingBox), new FrameworkPropertyMetadata(typeof(LoadingBox)));
        }

        public double RadiusX
        {
            get { return (double)GetValue(RadiusXProperty); }
            set { SetValue(RadiusXProperty, value); }
        }

        // Using a DependencyProperty as the backing store for RadiusX.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty RadiusXProperty =
            DependencyProperty.Register("RadiusX", typeof(double), typeof(LoadingBox), new PropertyMetadata(3d));



        public double RadiusY
        {
            get { return (double)GetValue(RadiusYProperty); }
            set { SetValue(RadiusYProperty, value); }
        }

        // Using a DependencyProperty as the backing store for RadiusY.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty RadiusYProperty =
            DependencyProperty.Register("RadiusY", typeof(double), typeof(LoadingBox), new PropertyMetadata(3d));

    }

依赖属性定义RadiusX,RadiusY半径坐标。

下面是实例调用代码:

<local:LoadingBox Grid.Column="0" Width="40" Height="40" RadiusX="3" RadiusY="3" Foreground="#000000"/>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值