WPF UI开发教程可重复执行按钮

开发项目中有一个需求,当鼠标按住Button时,产生连续触发增加文本框加减数字。不需要每点一次Button加减数字,需要用到RepeatButton按钮,该控件功能是按住Button事件可重复执行的按钮。

该控件中有两个重要属性

Delay:从用户按下鼠标左键到开始重复发送click事件的延迟时间.单位为毫秒 Delay数值必须大于等于0

Interval:当用户按下鼠标左键时,每次发出Click事件的时间间隔.单位为毫秒 Interval数值必须大于等于0

https://www.zhihu.com/video/1405481916824555520

1:RepeatButton按钮样式代码和按钮差不多:

<Style TargetType="{x:Type nb:NbRepeatButton}">
        <Setter Property="DisabledCursor" Value="No"/>
        <Setter Property="MaskBackground" Value="Transparent"/>
        <Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisualStyle}"/>
        <Setter Property="Background" Value="{StaticResource Nb.DefaultBtn.Background}" />
        <Setter Property="Foreground" Value="{StaticResource Nb.DefaultBtn.Foreground}" />
        <Setter Property="MinWidth" Value="50" />
        <Setter Property="MinHeight" Value="36" />
        <Setter Property="FontSize" Value="{StaticResource Nb.FontSize.28}" />
        <Setter Property="Margin" Value="0,0,0,0" />
        <Setter Property="CornerRadius" Value="8" />        
        <Setter Property="HorizontalContentAlignment" Value="Center"/>
        <Setter Property="VerticalContentAlignment" Value="Center"/>
        <Setter Property="Padding" Value="0"/>
        <Setter Property="Cursor" Value="Hand"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type nb:NbRepeatButton}">
                    <Border x:Name="border"
                            BorderBrush="{TemplateBinding BorderBrush}" 
                            BorderThickness="{TemplateBinding BorderThickness}" 
                            Background="{TemplateBinding Background}" 
                            CornerRadius="{TemplateBinding CornerRadius}"
                            Effect="{TemplateBinding Effect}"
                            SnapsToDevicePixels="True">
                        <Border x:Name="innerBorder" 
                                Background="{TemplateBinding MaskBackground}" 
                                CornerRadius="{TemplateBinding CornerRadius}" 
                                SnapsToDevicePixels="True">
                            <ContentPresenter x:Name="contentPresenter" 
                                ContentTemplate="{TemplateBinding ContentTemplate}" 
                                Content="{TemplateBinding Content}" 
                                ContentStringFormat="{TemplateBinding ContentStringFormat}" 
                                Focusable="False" 
                                HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                                Margin="{TemplateBinding Padding}" 
                                RecognizesAccessKey="True" 
                                SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
                                VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        </Border>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Style.Triggers>
            <Trigger Property="IsEnabled" Value="False">
                <Setter Property="Opacity" Value="0.6"/>
            </Trigger>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter Property="MaskBackground" Value="{StaticResource Nb.DefaultBtn.OverBackground}"/>
            </Trigger>
            <Trigger Property="IsPressed" Value="True">
                <Setter Property="MaskBackground" Value="{StaticResource Nb.DefaultBtn.PressedBackground}"/>
            </Trigger>
        </Style.Triggers>
    </Style>

2:RepeatButton按钮类依赖属性代码

/// <summary>
    /// 按下事件可重复执行的按钮
    /// </summary>
    public class NbRepeatButton : RepeatButton
        #region ctor
        static NbRepeatButton()
            DefaultStyleKeyProperty.OverrideMetadata(typeof(NbRepeatButton), new FrameworkPropertyMetadata(typeof(NbRepeatButton)));
        /// <summary>
        /// </summary>
        public NbRepeatButton()
            IsHitTestVisibleInChrome = true;
        #endregion
        #region prop
        /// <summary>
        /// 非客户区鼠标/触摸响应
        /// </summary>
        public bool IsHitTestVisibleInChrome
            get { return WindowChrome.GetIsHitTestVisibleInChrome(this); }
            set { WindowChrome.SetIsHitTestVisibleInChrome(this, value); }
        #endregion
        #region dp prop
        /// <summary>
        /// 圆角
        /// </summary>
        public CornerRadius CornerRadius
            get { return (CornerRadius)GetValue(CornerRadiusProperty); }
            set { SetValue(CornerRadiusProperty, value); }
        // Using a DependencyProperty as the backing store for CornerRadius.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CornerRadiusProperty =
            DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(NbRepeatButton), new PropertyMetadata(new CornerRadius(0d)));
        /// <summary>
        /// 遮罩层背景色(用于鼠标移入和点击按钮时背景色变化)
        /// </summary>
        public Brush MaskBackground
            get { return (Brush)GetValue(MaskBackgroundProperty); }
            set { SetValue(MaskBackgroundProperty, value); }
        // Using a DependencyProperty as the backing store for MaskBackground.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MaskBackgroundProperty =
            DependencyProperty.Register("MaskBackground", typeof(Brush), typeof(NbRepeatButton), new PropertyMetadata(Brushes.Transparent));
        /// <summary>
        /// 禁用时鼠标的样式
        /// </summary>
        public Cursor DisabledCursor
            get { return (Cursor)GetValue(DisabledCursorProperty); }
            set { SetValue(DisabledCursorProperty, value); }
        // Using a DependencyProperty as the backing store for DisabledCursor.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DisabledCursorProperty =
            DependencyProperty.Register("DisabledCursor", typeof(Cursor), typeof(NbRepeatButton), new PropertyMetadata(Cursors.No, (d, e) =>
                var ele = (UIElement)d;
                ele.AddAdorner(new DisabledAdorner(ele, (Cursor)e.NewValue));
        #endregion
        #region override
        /// <summary>
        /// </summary>
        public override void OnApplyTemplate()
            base.OnApplyTemplate();
            this.AddAdorner(new DisabledAdorner(this, DisabledCursor));
        /// <summary>
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)