WPF流动的点

public class FlowingPoint : Control
    {
        static FlowingPoint()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(FlowingPoint), new FrameworkPropertyMetadata(typeof(FlowingPoint)));
        }

        #region Property
        StackPanel stack = null;
        Ellipse t = null;

        #region 点大小
        public double PointSize
        {
            get { return (double)GetValue(PointSizeProperty); }
            set { SetValue(PointSizeProperty, value); }
        }

        // Using a DependencyProperty as the backing store for PointSize.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PointSizeProperty =
            DependencyProperty.Register("PointSize", typeof(double), typeof(FlowingPoint), new PropertyMetadata(10d, OnPropertyChanged));
        #endregion

        #region 点颜色
        public Brush PointBrush
        {
            get { return (Brush)GetValue(PointBrushProperty); }
            set { SetValue(PointBrushProperty, value); }
        }

        // Using a DependencyProperty as the backing store for PointBrush.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PointBrushProperty =
            DependencyProperty.Register("PointBrush", typeof(Brush), typeof(FlowingPoint), new PropertyMetadata(Brushes.Red, OnPropertyChanged));
        #endregion

        #region 方向
        public Orientation Orientation
        {
            get { return (Orientation)GetValue(OrientationProperty); }
            set { SetValue(OrientationProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Orientation.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty OrientationProperty =
            DependencyProperty.Register("Orientation", typeof(Orientation), typeof(FlowingPoint), new PropertyMetadata(Orientation.Horizontal, OnPropertyChanged));
        #endregion

        #region 是否流动
        public bool IsFlowing
        {
            get { return (bool)GetValue(IsFlowingProperty); }
            set { SetValue(IsFlowingProperty, value); }
        }

        // Using a DependencyProperty as the backing store for IsFlowing.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsFlowingProperty =
            DependencyProperty.Register("IsFlowing", typeof(bool), typeof(FlowingPoint), new PropertyMetadata(true));
        #endregion
        #endregion

        #region OnPropertyChanged
        private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d == null
                || !(d is FlowingPoint))
            {
                return;
            }

            (d as FlowingPoint).UpdatePoint();
        }
        #endregion

        #region OnApplyTemplate
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            stack = (StackPanel)this.Template.FindName("stackPanel", this);
            t = (Ellipse)this.Template.FindName("t", this);
        }
        #endregion

        #region OnRender
        protected override void OnRender(DrawingContext drawingContext)
        {
            base.OnRender(drawingContext);
            UpdatePoint();
        }
        #endregion

        #region UpdatePoint()
        private void UpdatePoint()
        {
            if (stack == null)
            {
                return;
            }

            IsFlowing = false;
            while (stack.Children.Count > 1)
            {
                stack.Children.RemoveAt(1);
            }
            if (Orientation == Orientation.Horizontal)
            {
                t.Margin = new Thickness(-10, 0, 0, 0);
                if (ActualWidth == 0)
                {
                    return;
                }

                for (int i = 0; i < ActualWidth / 10; i++)
                {
                    stack.Children.Add(new Ellipse() { Fill = PointBrush, Width = PointSize, Height = PointSize, Margin = new Thickness(10, 0, 0, 0) });
                }
            }
            else
            {
                t.Margin = new Thickness(0, -10, 0, 0);
                if (ActualHeight == 0)
                {
                    return;
                }

                for (int i = 0; i < ActualHeight / 10; i++)
                {
                    stack.Children.Add(new Ellipse() { Fill = PointBrush, Width = PointSize, Height = PointSize, Margin = new Thickness(0, 10, 0, 0) });
                }
            }
        }
        #endregion
    }
<Style TargetType="{x:Type local:FlowingPoint}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:FlowingPoint}">
                    <StackPanel x:Name="stackPanel" Background="{TemplateBinding Background}"
                                Orientation="{Binding Orientation,RelativeSource={RelativeSource Mode=TemplatedParent}}">
                        <Ellipse x:Name="t" Width="{Binding PointSize,RelativeSource={RelativeSource Mode=TemplatedParent}}"
                                 Height="{Binding PointSize,RelativeSource={RelativeSource Mode=TemplatedParent}}"
                                 Fill="{Binding PointBrush,RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
                    </StackPanel>
                    <ControlTemplate.Triggers>
                        <MultiDataTrigger>
                            <MultiDataTrigger.Conditions>
                                <Condition Binding="{Binding Orientation,RelativeSource={RelativeSource Mode=Self}}" Value="Horizontal"/>
                                <Condition Binding="{Binding IsFlowing,RelativeSource={RelativeSource Mode=Self}}" Value="true"/>
                            </MultiDataTrigger.Conditions>
                            <MultiDataTrigger.EnterActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <ThicknessAnimation Duration="00:00:03" From="-10,0,0,0" To="0,0,0,0" RepeatBehavior="Forever"
                                                            Storyboard.TargetName="t" Storyboard.TargetProperty="Margin"/>
                                    </Storyboard>
                                </BeginStoryboard>
                            </MultiDataTrigger.EnterActions>
                        </MultiDataTrigger>
                        <MultiDataTrigger>
                            <MultiDataTrigger.Conditions>
                                <Condition Binding="{Binding Orientation,RelativeSource={RelativeSource Mode=Self}}" Value="Vertical"/>
                                <Condition Binding="{Binding IsFlowing,RelativeSource={RelativeSource Mode=Self}}" Value="true"/>
                            </MultiDataTrigger.Conditions>
                            <MultiDataTrigger.EnterActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <ThicknessAnimation Duration="00:00:03" From="0,-10,0,0" To="0,0,0,0" RepeatBehavior="Forever"
                                                            Storyboard.TargetName="t" Storyboard.TargetProperty="Margin"/>
                                    </Storyboard>
                                </BeginStoryboard>
                            </MultiDataTrigger.EnterActions>
                        </MultiDataTrigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值