• WPF时间长度自定义选择控件TimeSpanBox


    以下控件采用https://www.cnblogs.com/cssmystyle/archive/2011/01/17/1937361.html部分代码

    以下控件采用https://www.cnblogs.com/xiaomingg/p/11180355.html部分代码

    TimeSpanBox 效果如下,用于选择时间的长度,年最大值99,月最大值11,日最大值30,时最大值23,分最大值59,秒最大值59

    第一步,新建WPF用户TimepanBox

    <UserControl x:Class="WPFApp.Controls.TimeSpanBox.TimeSpanBox"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 xmlns:local="clr-namespace:WPFApp.Controls.TimeSpanBox"             
                 BorderBrush="Gray" BorderThickness="1" mc:Ignorable="d"     Focusable="False"        
                 d:DesignHeight="25" d:DesignWidth="200">
        <UserControl.Resources>
            <ControlTemplate x:Key="UPBtnTemplate" TargetType="{x:Type RepeatButton}">
                <Border BorderThickness="0">
                    <Border.Background>
                        <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0" Opacity="1">
                            <GradientStop Color="#FFF9FAFB" Offset="0" />
                            <GradientStop Color="#FFC4CCD4" Offset="0.973" />
                        </LinearGradientBrush>
                    </Border.Background>
                    <ContentPresenter HorizontalAlignment="Center" Content="{TemplateBinding Button.Content}" VerticalAlignment="Center"/>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsPressed" Value="True">
                        <Setter Property="RenderTransform">
                            <Setter.Value>
                                <TranslateTransform X=".5" Y=".3"/>
                            </Setter.Value>
                        </Setter>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
            <ControlTemplate x:Key="DownBtnTemplate" TargetType="{x:Type RepeatButton}">
                <Border BorderThickness="0">
                    <Border.Background>
                        <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0" Opacity="1">
                            <GradientStop Color="#FFC4CCD4" Offset="0.973" />
                            <GradientStop Color="#FFF9FAFB" Offset="0" />
                        </LinearGradientBrush>
                    </Border.Background>
                    <ContentPresenter HorizontalAlignment="Center" Content="{TemplateBinding Button.Content}" VerticalAlignment="Center"/>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsPressed" Value="True">
                        <Setter Property="RenderTransform">
                            <Setter.Value>
                                <TranslateTransform X=".5" Y=".3"/>
                            </Setter.Value>
                        </Setter>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </UserControl.Resources>
        <Grid Background="White">
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition Width="auto"/>
                <ColumnDefinition/>
                <ColumnDefinition Width="auto"/>
                <ColumnDefinition/>
                <ColumnDefinition Width="auto"/>
                <ColumnDefinition/>
                <ColumnDefinition Width="auto"/>
                <ColumnDefinition/>
                <ColumnDefinition Width="auto"/>
                <ColumnDefinition/>
                <ColumnDefinition Width="auto"/>
                <ColumnDefinition Width="auto"/>
            </Grid.ColumnDefinitions>
            <TextBox Grid.Column="0" BorderBrush="Transparent" BorderThickness="0" x:Name="txtYear" VerticalContentAlignment="Center"
                     InputMethod.IsInputMethodEnabled="False" TextAlignment="Right" Padding="0,0,1,0"/>
            <TextBlock Text="年" Grid.Column="1" VerticalAlignment="Center" x:Name="txtbYear"/>
            <TextBox Grid.Column="2" BorderBrush="Transparent" BorderThickness="0" x:Name="txtMonth" VerticalContentAlignment="Center"
                     InputMethod.IsInputMethodEnabled="False"  TextAlignment="Right" Padding="0,0,1,0"/>
            <TextBlock Text="月" Grid.Column="3" VerticalAlignment="Center" x:Name="txtbMonth"/>
            <TextBox Grid.Column="4" BorderBrush="Transparent" BorderThickness="0" x:Name="txtDay" VerticalContentAlignment="Center"
                     InputMethod.IsInputMethodEnabled="False" TextAlignment="Right" Padding="0,0,1,0"/>
            <TextBlock Text="天" Grid.Column="5" VerticalAlignment="Center" x:Name="txtbDay"/>
            <TextBox Grid.Column="6" BorderBrush="Transparent" BorderThickness="0" x:Name="txtHour" VerticalContentAlignment="Center"
                     InputMethod.IsInputMethodEnabled="False" TextAlignment="Right" Padding="0,0,1,0"/>
            <TextBlock Text="时" Grid.Column="7" VerticalAlignment="Center" x:Name="txtbHour"/>
            <TextBox Grid.Column="8" BorderBrush="Transparent" BorderThickness="0" x:Name="txtMinute" VerticalContentAlignment="Center"
                     InputMethod.IsInputMethodEnabled="False" TextAlignment="Right" Padding="0,0,1,0"/>
            <TextBlock Text="分" Grid.Column="9" VerticalAlignment="Center" x:Name="txtbMinute"/>
            <TextBox Grid.Column="10" BorderBrush="Transparent" BorderThickness="0" x:Name="txtSecound" VerticalContentAlignment="Center"
                     InputMethod.IsInputMethodEnabled="False" TextAlignment="Right" Padding="0,0,1,0"/>
            <TextBlock Text="秒" Grid.Column="11" VerticalAlignment="Center" x:Name="txtbSecound"/>
            <UniformGrid Grid.Column="12" Rows="2" x:Name="gridShow" Margin="1,0,0,0">
                <RepeatButton Padding="0" Width="{Binding RelativeSource={RelativeSource Mode=Self},Path=ActualHeight}" Focusable="False"
                        VerticalContentAlignment="Center" Template="{StaticResource UPBtnTemplate}" Command="{x:Static local:TimeSpanBox.IncreaseCommand}">
                    <Path Height="6" Width="12" Stretch="Fill" Opacity="1" Fill="#FF554646"
                        Data="M 666.5,597 C666.5,597 678.5,597 678.5,597 678.5,597 672.5,591 672.5,591 672.5,591 666.5,597 666.5,597 z"/>
                </RepeatButton>
                <RepeatButton Padding="0" Width="{Binding RelativeSource={RelativeSource Mode=Self},Path=ActualHeight}" Focusable="False"
                        VerticalContentAlignment="Center" Template="{StaticResource DownBtnTemplate}" Command="{x:Static local:TimeSpanBox.DecreaseCommand}">
                    <Path Height="6" Width="12" Stretch="Fill" Opacity="1" Fill="#FF554646"
                            Data="M 666.5,609 C666.5,609 678.5,609 678.5,609 678.5,609 672.5,615 672.5,615 672.5,615 666.5,609 666.5,609 z"/>
                </RepeatButton>
            </UniformGrid>
        </Grid>
    </UserControl>

    对应自定义用户控件的后台代码

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    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 WPFApp.Controls.TimeSpanBox
    {
        public partial class TimeSpanBox : UserControl
        {
            private TextBox previousFocus = null;
            public TimeSpanBox()
            {
                InitializeComponent();
    
                MouseButtonEventHandler PreviewMouseDown = (o1, e1) =>
                {
                    TextBox textbox = o1 as TextBox;
                    if (textbox != null)
                    {
                        textbox.Focus();
                        e1.Handled = true;
                    }
                };
                txtYear.PreviewMouseDown += PreviewMouseDown;
                txtMonth.PreviewMouseDown += PreviewMouseDown;
                txtDay.PreviewMouseDown += PreviewMouseDown;
                txtHour.PreviewMouseDown += PreviewMouseDown;
                txtMinute.PreviewMouseDown += PreviewMouseDown;
                txtSecound.PreviewMouseDown += PreviewMouseDown;
    
                RoutedEventHandler GotFocus = (o1, e1) =>
                {
                    TextBox txt = o1 as TextBox;
                    if (txt != null)
                    {
                        txt.SelectAll();
                        txt.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FFBFEDF1"));
                        txt.Foreground = new SolidColorBrush(Colors.Black);
                        txt.PreviewMouseDown -= new MouseButtonEventHandler(PreviewMouseDown);
                    }
                    previousFocus = txt;
                };
                txtYear.GotFocus += GotFocus;
                txtMonth.GotFocus += GotFocus;
                txtDay.GotFocus += GotFocus;
                txtHour.GotFocus += GotFocus;
                txtMinute.GotFocus += GotFocus;
                txtSecound.GotFocus += GotFocus;
    
    
                RoutedEventHandler LostFocus = (o1, e1) =>
                {
                    var textBox = o1 as TextBox;
                    if (textBox != null)
                    {
                        textBox.Background = new SolidColorBrush(Colors.Transparent);
                        textBox.Foreground = new SolidColorBrush(Colors.Black);
                        textBox.PreviewMouseDown += new MouseButtonEventHandler(PreviewMouseDown);
                    }
                };
                txtYear.LostFocus += LostFocus;
                txtMonth.LostFocus += LostFocus;
                txtDay.LostFocus += LostFocus;
                txtHour.LostFocus += LostFocus;
                txtMinute.LostFocus += LostFocus;
                txtSecound.LostFocus += LostFocus;
    
    
                KeyEventHandler KeyDowm = (o1, e1) =>
                {
                    TextBox txt = o1 as TextBox;
                    if (e1.Key == Key.Enter || (e1.Key == Key.Right && txt.SelectionStart == txt.Text.Length))
                    {
                        FocusNextText(txt);
                    }
                    else if (((e1.Key == Key.Delete || e1.Key == Key.Back) && (txt.Text == "0" || string.IsNullOrEmpty(txt.Text))) ||
                        (txt.SelectionStart == 0 && e1.Key == Key.Left)
                    )
                    {
                        e1.Handled = true;
                        if (!(txt.SelectionStart == 0 && e1.Key == Key.Left))
                            txt.Text = "0";
                        FocusPreviousText(txt);
                    }
                };
    
                txtYear.PreviewKeyDown += KeyDowm;
                txtMonth.PreviewKeyDown += KeyDowm;
                txtDay.PreviewKeyDown += KeyDowm;
                txtHour.PreviewKeyDown += KeyDowm;
                txtMinute.PreviewKeyDown += KeyDowm;
                txtSecound.PreviewKeyDown += KeyDowm;
    
    
                txtYear.TextChanged += TextYear_Changed;
                txtMonth.TextChanged += txtMonth_Changed;
                txtDay.TextChanged += txtDay_Changed;
                txtHour.TextChanged += txtHour_Changed;
                txtMinute.TextChanged += txtMinute_Changed;
                txtSecound.TextChanged += txtSecound_Changed;
                
    
                txtbYear.MouseLeftButtonDown += (o1, e1) => { txtYear.Focus(); txtYear.SelectAll(); };
                txtbMonth.MouseLeftButtonDown += (o1, e1) => { txtMonth.Focus(); txtMonth.SelectAll(); };
                txtbDay.MouseLeftButtonDown += (o1, e1) => { txtDay.Focus(); txtDay.SelectAll(); };
                txtbHour.MouseLeftButtonDown += (o1, e1) => { txtHour.Focus(); txtHour.SelectAll(); };
                txtbMinute.MouseLeftButtonDown += (o1, e1) => { txtMinute.Focus(); txtMinute.SelectAll(); };
                txtbSecound.MouseLeftButtonDown += (o1, e1) => { txtSecound.Focus(); txtSecound.SelectAll(); };
    
                this.SetTextBoxBindingText(this.txtYear, "YearText");
                this.SetTextBoxBindingText(this.txtMonth, "MonthText");
                this.SetTextBoxBindingText(this.txtDay, "DayText");
                this.SetTextBoxBindingText(this.txtHour, "HourText");
                this.SetTextBoxBindingText(this.txtMinute, "MinuteText");
                this.SetTextBoxBindingText(this.txtSecound, "SecoundText");
            }
            private void SetTextBoxBindingText(TextBox targetTxt,string bindingPath)
            {
                Binding binding = new Binding(bindingPath);
                binding.Source = this;
                binding.Mode = BindingMode.TwoWay;
                binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
                targetTxt.SetBinding(TextBox.TextProperty, binding);
            }
    
            #region 注册路由命令
            #region 注册鼠标左键按下事件
            static TimeSpanBox()
            {
                InitializeCommands();
                //EventManager.RegisterClassHandler(typeof(TimeSpanBox),
                //   Mouse.MouseDownEvent, new MouseButtonEventHandler(TimeSpanBox.OnMouseLeftButtonDown), true);
            }
            private static void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
                TimeSpanBox control = (TimeSpanBox)sender;
                //如果某人点击控件的部分只,但是该控件没有聚焦,
                //本空间需要获取焦点来处理正确处理键盘
                if (!control.IsKeyboardFocusWithin)//获取一个值,该值指示键盘焦点是否处于元素边界内的任何位置(包括键盘焦点是否位于任何可视子元素的边界内)。
                {
                    e.Handled = control.Focus() || e.Handled;
                }
            }
            #endregion
    
            private static RoutedCommand m_IncreaseCommand;
            private static RoutedCommand m_DecreaseCommand;
            public static RoutedCommand IncreaseCommand
            {
                get
                {
                    return m_IncreaseCommand;
                }
            }
            public static RoutedCommand DecreaseCommand
            {
                get
                {
                    return m_DecreaseCommand;
                }
            }
            private static void InitializeCommands()
            {
                m_IncreaseCommand = new RoutedCommand("IncreaseCommand", typeof(TimeSpanBox));
                CommandManager.RegisterClassCommandBinding(typeof(TimeSpanBox), new CommandBinding(m_IncreaseCommand, OnIncreaseCommand));
                CommandManager.RegisterClassInputBinding(typeof(TimeSpanBox), new InputBinding(m_IncreaseCommand, new KeyGesture(Key.Up)));
    
                m_DecreaseCommand = new RoutedCommand("DecreaseCommand", typeof(TimeSpanBox));
                CommandManager.RegisterClassCommandBinding(typeof(TimeSpanBox), new CommandBinding(m_DecreaseCommand, OnDecreaseCommand));
                CommandManager.RegisterClassInputBinding(typeof(TimeSpanBox), new InputBinding(m_DecreaseCommand, new KeyGesture(Key.Down)));
            }
    
            private static void OnDecreaseCommand(object sender, ExecutedRoutedEventArgs e)
            {
                TimeSpanBox control = sender as TimeSpanBox;
                if (control != null && control.previousFocus != null)
                {
                    if (control.previousFocus == control.txtYear)
                    {
                        control.Year = Math.Max(0, control.Year - 1);
                        control.txtYear.SelectAll();
                    }
                    else if (control.previousFocus == control.txtMonth)
                    {
                        control.Month = Math.Max(0, control.Month - 1);
                        control.txtMonth.SelectAll();
                    }
                    else if (control.previousFocus == control.txtDay)
                    {
                        control.Day = Math.Max(0, control.Day - 1);
                        control.txtDay.SelectAll();
                    }
                    else if (control.previousFocus == control.txtHour)
                    {
                        control.Hour = Math.Max(0, control.Hour - 1);
                        control.txtHour.SelectAll();
                    }
                    else if (control.previousFocus == control.txtMinute)
                    {
                        control.Minutes = Math.Max(0, control.Minutes - 1);
                        control.txtMinute.SelectAll();
                    }
                    else if (control.previousFocus == control.txtSecound)
                    {
                        control.Secound = Math.Max(0, control.Secound - 1);
                        control.txtSecound.SelectAll();
                    }
                }
            }
    
            private static void OnIncreaseCommand(object sender, ExecutedRoutedEventArgs e)
            {
                TimeSpanBox control = sender as TimeSpanBox;
                if (control != null)
                {
                    if (control.previousFocus == control.txtYear)
                    {
                        control.Year = Math.Min(99, control.Year + 1);
                        control.txtYear.SelectAll();
                    }
                    else if (control.previousFocus == control.txtMonth)
                    {
                        control.Month = Math.Min(11, control.Month + 1);
                        control.txtMonth.SelectAll();
                    }
                    else if (control.previousFocus == control.txtDay)
                    {
                        control.Day = Math.Min(30, control.Day + 1);
                        control.txtDay.SelectAll();
                    }
                    else if (control.previousFocus == control.txtHour)
                    {
                        control.Hour = Math.Min(23, control.Hour + 1);
                        control.txtHour.SelectAll();
                    }
                    else if (control.previousFocus == control.txtMinute)
                    {
                        control.Minutes = Math.Min(59, control.Minutes + 1);
                        control.txtMinute.SelectAll();
                    }
                    else if (control.previousFocus == control.txtSecound)
                    {
                        control.Secound = Math.Min(59, control.Secound + 1);
                        control.txtSecound.SelectAll();
                    }
                }
            }
            #endregion
    
            #region 跳转到上个文本框
            private void FocusNextText(TextBox currTxt)
            {
                TextBox[] textboxArray = new TextBox[] { txtYear, txtMonth, txtDay, txtHour, txtMinute, txtSecound };
                bool[] isVisibleArray = new bool[] { IsYearVisible, IsMonthVisible, IsDayVisible, IsHourVisible, IsMinuteVisible, IsSecoundVisible };
    
                int index = Array.IndexOf(textboxArray, currTxt);
                if (index != -1)
                {
                    var findTxt = textboxArray.Skip(index + 1).FirstOrDefault(txt => isVisibleArray[Array.IndexOf(textboxArray, txt)]);
                    if (findTxt != null)
                    {
                        findTxt.Focus();
                    }
                }
            }
            #endregion
            #region 跳转到下个文本框
            private void FocusPreviousText(TextBox currTxt)
            {
                TextBox[] textboxArray = new TextBox[] { txtYear, txtMonth, txtDay, txtHour, txtMinute, txtSecound };
                bool[] isVisibleArray = new bool[] { IsYearVisible, IsMonthVisible, IsDayVisible, IsHourVisible, IsMinuteVisible, IsSecoundVisible };
                int index = Array.IndexOf(textboxArray, currTxt);
                if (index != -1)
                {
                    var findTxt = textboxArray.Take(index).Reverse().FirstOrDefault(txt => isVisibleArray[Array.IndexOf(textboxArray, txt)]);
                    if (findTxt != null)
                    {
                        findTxt.Focus();
                    }
                }
            }
            #endregion
    
            #region 年份改变
            private bool CanRaiseTxtChaned_Year_AttachDP = true;
            private void TextYear_Changed(object sender, TextChangedEventArgs e)
            {
                string year = txtYear.Text;
                if (string.IsNullOrEmpty(year))
                {
                    SetYear(0);
                    if (txtYear.IsFocused == true)
                        txtYear.SelectAll();
                }
                else
                {
                    int newYear = 0;
                    bool result = int.TryParse(year, out newYear);
                    if (result == true && newYear >= 0 && this.Year != newYear)
                    {
                        if (newYear > 99)
                        {
                            SetText_Year("99");
                            SetYear(99);
                            txtMonth.Focus();
                        }
                        else
                        {
                            SetText_Year(newYear.ToString());
                            SetYear(newYear);
                        }
                        if (txtYear.Text.Length == 2)
                            FocusNextText(txtYear);
                    }
                    else
                    {
                        SetYear(0);
                        SetText_Year("0");
                    }
                }
            }
            private void SetText_Year(string newValue)
            {
                txtYear.TextChanged -= TextYear_Changed;
                txtYear.Text = newValue;
                txtYear.TextChanged += TextYear_Changed;
            }
            private void SetYear(int year)
            {
                CanRaiseTxtChaned_Year_AttachDP = false;
                this.Year = year;
                CanRaiseTxtChaned_Year_AttachDP = true;
            }
            #endregion
            #region 月份改变
            private bool CanRaiseTxtChaned_Month_AttachDP = true;
            private void txtMonth_Changed(object sender, TextChangedEventArgs e)
            {
                string month = txtMonth.Text;
                if (string.IsNullOrEmpty(month))
                {
                    SetMonth(0);
                    if (txtMonth.IsFocused == true)
                        txtMonth.SelectAll();
                }
                else
                {
                    int newMonth = 0;
                    bool result = int.TryParse(month, out newMonth);
                    if (result == true && newMonth >= 0 && this.Month != newMonth)
                    {
                        if (newMonth > 11)
                        {
                            SetText_Month("11");
                            SetMonth(11);
                            txtDay.Focus();
                        }
                        else
                        {
                            SetText_Month(newMonth.ToString());
                            SetMonth(newMonth);
                        }
                        if (txtMonth.Text.Length == 2)
                            FocusNextText(txtMonth);
                    }
                    else
                    {
                        SetMonth(0);
                        SetText_Month("0");
                    }
                }
            }
            private void SetText_Month(string newValue)
            {
                txtMonth.TextChanged -= txtMonth_Changed;
                txtMonth.Text = newValue;
                txtMonth.TextChanged += txtMonth_Changed;
            }
            private void SetMonth(int month)
            {
                CanRaiseTxtChaned_Month_AttachDP = false;
                this.Month = month;
                CanRaiseTxtChaned_Month_AttachDP = true;
            }
            #endregion
            #region 日改变
            private bool CanRaiseTxtChaned_Day_AttachDP = true;
            private void txtDay_Changed(object sender, TextChangedEventArgs e)
            {
                string day = txtDay.Text;
                if (string.IsNullOrEmpty(day))
                {
                    SetDay(0);
                    if (txtDay.IsFocused == true)
                        txtDay.SelectAll();
                }
                else
                {
                    int newDay = 0;
                    bool result = int.TryParse(day, out newDay);
                    if (result == true && newDay >= 0 && this.Day != newDay)
                    {
                        if (newDay > 30)
                        {
                            SetText_Day("30");
                            SetDay(30);
                            txtHour.Focus();
                        }
                        else
                        {
                            SetText_Day(newDay.ToString());
                            SetDay(newDay);
                        }
                        if (txtDay.Text.Length == 2)
                            FocusNextText(txtDay);
                    }
                    else
                    {
                        SetDay(0);
                        SetText_Day("0");
                    }
                }
            }
            private void SetText_Day(string newValue)
            {
                txtDay.TextChanged -= txtDay_Changed;
                txtDay.Text = newValue;
                txtDay.TextChanged += txtDay_Changed;
            }
            private void SetDay(int day)
            {
                CanRaiseTxtChaned_Day_AttachDP = false;
                this.Day = day;
                CanRaiseTxtChaned_Day_AttachDP = true;
            }
            #endregion
            #region 时改变
            private bool CanRaiseTxtChaned_Hour_AttachDP = true;
            private void txtHour_Changed(object sender, TextChangedEventArgs e)
            {
                string hour = txtHour.Text;
                if (string.IsNullOrEmpty(hour))
                {
                    SetDay(0);
                    if (txtHour.IsFocused == true)
                        txtHour.SelectAll();
                }
                else
                {
                    int newHour = 0;
                    bool result = int.TryParse(hour, out newHour);
                    if (result == true && newHour >= 0 && this.Hour != newHour)
                    {
                        if (newHour > 23)
                        {
                            SetText_Hour("23");
                            SetHour(23);
                            txtMinute.Focus();
                        }
                        else
                        {
                            SetText_Hour(newHour.ToString());
                            SetHour(newHour);
                        }
                        if (txtHour.Text.Length == 2)
                            FocusNextText(txtHour);
                    }
                    else
                    {
                        SetHour(0);
                        SetText_Hour("0");
                    }
                }
            }
            private void SetText_Hour(string newValue)
            {
                txtHour.TextChanged -= txtHour_Changed;
                txtHour.Text = newValue;
                txtHour.TextChanged += txtHour_Changed;
            }
            private void SetHour(int hour)
            {
                CanRaiseTxtChaned_Hour_AttachDP = false;
                this.Hour = hour;
                CanRaiseTxtChaned_Hour_AttachDP = true;
            }
            #endregion
            #region 分改变
            private bool CanRaiseTxtChaned_Minute_AttachDP = true;
            private void txtMinute_Changed(object sender, TextChangedEventArgs e)
            {
                string minute = txtMinute.Text;
                if (string.IsNullOrEmpty(minute))
                {
                    SetMinute(0);
                    if (txtMinute.IsFocused == true)
                        txtMinute.SelectAll();
                }
                else
                {
                    int newMinute = 0;
                    bool result = int.TryParse(minute, out newMinute);
                    if (result == true && newMinute >= 0 && this.Minutes != newMinute)
                    {
                        if (newMinute > 59)
                        {
                            SetText_Minute("59");
                            SetMinute(59);
                            txtSecound.Focus();
                        }
                        else
                        {
                            SetText_Minute(newMinute.ToString());
                            SetMinute(newMinute);
                        }
                        if (txtMinute.Text.Length == 2)
                            FocusNextText(txtMinute);
                    }
                    else
                    {
                        SetMinute(0);
                        SetText_Minute("0");
                    }
                }
            }
            private void SetText_Minute(string newValue)
            {
                txtMinute.TextChanged -= txtMinute_Changed;
                txtMinute.Text = newValue;
                txtMinute.TextChanged += txtMinute_Changed;
            }
            private void SetMinute(int Minute)
            {
                CanRaiseTxtChaned_Minute_AttachDP = false;
                this.Minutes = Minute;
                CanRaiseTxtChaned_Minute_AttachDP = true;
            }
            #endregion
            #region 秒改变
            private bool CanRaiseTxtChaned_Secound_AttachDP = true;
            private void txtSecound_Changed(object sender, TextChangedEventArgs e)
            {
                string secound = txtSecound.Text;
                if (string.IsNullOrEmpty(secound))
                {
                    SetSecound(0);
                    if (txtSecound.IsFocused == true)
                        txtSecound.SelectAll();
                }
                else
                {
                    int newSecound = 0;
                    bool result = int.TryParse(secound, out newSecound);
                    if (result == true && newSecound >= 0 && this.Secound != newSecound)
                    {
                        if (newSecound > 59)
                        {
                            SetText_Secound("59");
                            SetSecound(59);
                            txtSecound.SelectionStart = txtSecound.Text.Length;
                        }
                        else
                        {
                            SetText_Secound(newSecound.ToString());
                            SetSecound(newSecound);
                        }
                    }
                    else
                    {
                        SetSecound(0);
                        SetText_Secound("0");
                    }
                }
            }
            private void SetText_Secound(string newValue)
            {
                txtSecound.TextChanged -= txtSecound_Changed;
                txtSecound.Text = newValue;
                txtSecound.TextChanged += txtSecound_Changed;
            }
            private void SetSecound(int secound)
            {
                CanRaiseTxtChaned_Secound_AttachDP = false;
                this.Secound = secound;
                CanRaiseTxtChaned_Secound_AttachDP = true;
            }
            #endregion
    
            #region IsYearVisible
            public bool IsYearVisible
            {
                get { return (bool)GetValue(IsYearVisibleProperty); }
                set { SetValue(IsYearVisibleProperty, value); }
            }
    
            public static readonly DependencyProperty IsYearVisibleProperty =
                DependencyProperty.Register("IsYearVisible", typeof(bool), typeof(TimeSpanBox), new PropertyMetadata(true, On_IsYearVisible));
    
            private static void On_IsYearVisible(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                TimeSpanBox sender = d as TimeSpanBox;
                if (sender != null)
                {
                    Grid innerGrid = (Grid)sender.Content;
                    innerGrid.ColumnDefinitions[0].Width = e.NewValue != null && e.NewValue is bool && (bool)e.NewValue == true
                        ? new GridLength(1, GridUnitType.Star) : new GridLength(0);
                    innerGrid.ColumnDefinitions[1].Width = e.NewValue != null && e.NewValue is bool && (bool)e.NewValue == true
                        ? GridLength.Auto : new GridLength(0);
                    if (innerGrid.ColumnDefinitions[0].Width == new GridLength(0))
                    {
                        sender.SetText_Year("0");
                        sender.CanRaiseTxtChaned_Year_AttachDP = false;
                        sender.Year = 0;
                        sender.CanRaiseTxtChaned_Year_AttachDP = true;
                    }
                }
            }
            #endregion
            #region IsMonthVisible
            public bool IsMonthVisible
            {
                get { return (bool)GetValue(IsMonthVisibleProperty); }
                set { SetValue(IsMonthVisibleProperty, value); }
            }
    
            public static readonly DependencyProperty IsMonthVisibleProperty =
                DependencyProperty.Register("IsMonthVisible", typeof(bool), typeof(TimeSpanBox), new PropertyMetadata(true, On_IsMonthVisible));
    
            private static void On_IsMonthVisible(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                TimeSpanBox sender = d as TimeSpanBox;
                if (sender != null)
                {
                    Grid innerGrid = (Grid)sender.Content;
                    innerGrid.ColumnDefinitions[2].Width = e.NewValue != null && e.NewValue is bool && (bool)e.NewValue == true
                        ? new GridLength(1, GridUnitType.Star) : new GridLength(0);
                    innerGrid.ColumnDefinitions[3].Width = e.NewValue != null && e.NewValue is bool && (bool)e.NewValue == true
                        ? GridLength.Auto : new GridLength(0);
                }
            }
            #endregion
            #region IsDayVisible
            public bool IsDayVisible
            {
                get { return (bool)GetValue(IsDayVisibleProperty); }
                set { SetValue(IsDayVisibleProperty, value); }
            }
    
            public static readonly DependencyProperty IsDayVisibleProperty =
                DependencyProperty.Register("IsDayVisible", typeof(bool), typeof(TimeSpanBox), new PropertyMetadata(true, On_IsDayVisible));
    
            private static void On_IsDayVisible(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                TimeSpanBox sender = d as TimeSpanBox;
                if (sender != null)
                {
                    Grid innerGrid = (Grid)sender.Content;
                    innerGrid.ColumnDefinitions[4].Width = e.NewValue != null && e.NewValue is bool && (bool)e.NewValue == true
                      ? new GridLength(1, GridUnitType.Star) : new GridLength(0);
                    innerGrid.ColumnDefinitions[5].Width = e.NewValue != null && e.NewValue is bool && (bool)e.NewValue == true
                        ? GridLength.Auto : new GridLength(0);
                }
            }
            #endregion
            #region IsHourVisible
            public bool IsHourVisible
            {
                get { return (bool)GetValue(IsHourVisibleProperty); }
                set { SetValue(IsHourVisibleProperty, value); }
            }
    
            public static readonly DependencyProperty IsHourVisibleProperty =
                DependencyProperty.Register("IsHourVisible", typeof(bool), typeof(TimeSpanBox), new PropertyMetadata(true, On_IsHourVisible));
    
            private static void On_IsHourVisible(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                TimeSpanBox sender = d as TimeSpanBox;
                if (sender != null)
                {
                    Grid innerGrid = (Grid)sender.Content;
                    innerGrid.ColumnDefinitions[6].Width = e.NewValue != null && e.NewValue is bool && (bool)e.NewValue == true
                    ? new GridLength(1, GridUnitType.Star) : new GridLength(0);
                    innerGrid.ColumnDefinitions[7].Width = e.NewValue != null && e.NewValue is bool && (bool)e.NewValue == true
                        ? GridLength.Auto : new GridLength(0);
                }
            }
            #endregion
            #region IsMinuteVisible
            public bool IsMinuteVisible
            {
                get { return (bool)GetValue(IsMinuteVisibleProperty); }
                set { SetValue(IsMinuteVisibleProperty, value); }
            }
    
            public static readonly DependencyProperty IsMinuteVisibleProperty =
                DependencyProperty.Register("IsMinuteVisible", typeof(bool), typeof(TimeSpanBox), new PropertyMetadata(true, On_IsMinuteVisible));
    
            private static void On_IsMinuteVisible(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                TimeSpanBox sender = d as TimeSpanBox;
                if (sender != null)
                {
                    Grid innerGrid = (Grid)sender.Content;
                    innerGrid.ColumnDefinitions[8].Width = e.NewValue != null && e.NewValue is bool && (bool)e.NewValue == true
                    ? new GridLength(1, GridUnitType.Star) : new GridLength(0);
                    innerGrid.ColumnDefinitions[9].Width = e.NewValue != null && e.NewValue is bool && (bool)e.NewValue == true
                        ? GridLength.Auto : new GridLength(0);
                }
            }
            #endregion
            #region IsSecoundVisible
            public bool IsSecoundVisible
            {
                get { return (bool)GetValue(IsSecoundVisibleProperty); }
                set { SetValue(IsSecoundVisibleProperty, value); }
            }
    
            public static readonly DependencyProperty IsSecoundVisibleProperty =
                DependencyProperty.Register("IsSecoundVisible", typeof(bool), typeof(TimeSpanBox), new PropertyMetadata(true, On_IsSecoundVisible));
    
            private static void On_IsSecoundVisible(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                TimeSpanBox sender = d as TimeSpanBox;
                if (sender != null)
                {
                    Grid innerGrid = (Grid)sender.Content;
                    innerGrid.ColumnDefinitions[10].Width = e.NewValue != null && e.NewValue is bool && (bool)e.NewValue == true
                 ? new GridLength(1, GridUnitType.Star) : new GridLength(0);
                    innerGrid.ColumnDefinitions[11].Width = e.NewValue != null && e.NewValue is bool && (bool)e.NewValue == true
                        ? GridLength.Auto : new GridLength(0);
                }
            }
            #endregion
    
            #region IsReadOnly
            public bool IsReadOnly
            {
                get { return (bool)GetValue(IsReadOnlyProperty); }
                set { SetValue(IsReadOnlyProperty, value); }
            }
            public static readonly DependencyProperty IsReadOnlyProperty =
                DependencyProperty.Register("IsReadOnly", typeof(bool), typeof(TimeSpanBox), new PropertyMetadata(false, OnIsReadOnly_Changed));
    
            private static void OnIsReadOnly_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                TimeSpanBox sender = d as TimeSpanBox;
                if (sender != null)
                {
                    bool isreadOnly = e.NewValue != null && e.NewValue is bool && (bool)e.NewValue == true;
                    sender.txtYear.IsReadOnly = isreadOnly;
                    sender.txtYear.IsReadOnly = isreadOnly;
                    sender.txtYear.IsReadOnly = isreadOnly;
                    sender.txtYear.IsReadOnly = isreadOnly;
                    sender.txtYear.IsReadOnly = isreadOnly;
                    sender.txtYear.IsReadOnly = isreadOnly;
                }
            }
            #endregion        
            #region Year
            public int Year
            {
                get { return (int)GetValue(YearProperty); }
                set { SetValue(YearProperty, value); }
            }
            public static readonly DependencyProperty YearProperty =
                DependencyProperty.Register("Year", typeof(int), typeof(TimeSpanBox), new PropertyMetadata(0, On_Year_Changed));
    
            private static void On_Year_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                TimeSpanBox selector = d as TimeSpanBox;
                if (selector != null && selector.CanRaiseTxtChaned_Year_AttachDP == true)
                {
                    if (e.NewValue == null)
                        selector.SetText_Year("");
                    else if (e.NewValue.GetType().Equals(typeof(int)))
                    {
                        selector.SetText_Year(int.Parse(e.NewValue.ToString()).ToString());
                    }
                    else
                    {
                        selector.SetText_Year("0");
                    }
                }
            }
            #endregion
            #region Month
            public int Month
            {
                get { return (int)GetValue(MonthProperty); }
                set { SetValue(MonthProperty, value); }
            }
            public static readonly DependencyProperty MonthProperty =
                DependencyProperty.Register("Month", typeof(int), typeof(TimeSpanBox), new PropertyMetadata(0, On_Month_Changed));
            private static void On_Month_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                TimeSpanBox selector = d as TimeSpanBox;
                if (selector != null && selector.CanRaiseTxtChaned_Month_AttachDP == true)
                {
                    if (e.NewValue == null)
                        selector.SetText_Month("");
                    else if (e.NewValue.GetType().Equals(typeof(int)))
                    {
                        selector.SetText_Month(int.Parse(e.NewValue.ToString()).ToString());
                    }
                    else
                    {
                        selector.SetText_Month("0");
                    }
                }
            }
            #endregion
            #region Day
            public int Day
            {
                get { return (int)GetValue(DayProperty); }
                set { SetValue(DayProperty, value); }
            }
            public static readonly DependencyProperty DayProperty =
                DependencyProperty.Register("Day", typeof(int), typeof(TimeSpanBox), new PropertyMetadata(0, ON_Day_Changed));
    
            private static void ON_Day_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                TimeSpanBox selector = d as TimeSpanBox;
                if (selector != null && selector.CanRaiseTxtChaned_Day_AttachDP == true)
                {
                    if (e.NewValue == null)
                        selector.SetText_Day("");
                    else if (e.NewValue.GetType().Equals(typeof(int)))
                    {
                        selector.SetText_Day(int.Parse(e.NewValue.ToString()).ToString());
                    }
                    else
                    {
                        selector.SetText_Day("0");
                    }
                }
            }
            #endregion
            #region Hour
            public int Hour
            {
                get { return (int)GetValue(HourProperty); }
                set { SetValue(HourProperty, value); }
            }
            public static readonly DependencyProperty HourProperty =
                DependencyProperty.Register("Hour", typeof(int), typeof(TimeSpanBox), new PropertyMetadata(0, On_Hour_CHanged));
            private static void On_Hour_CHanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                TimeSpanBox selector = d as TimeSpanBox;
                if (selector != null && selector.CanRaiseTxtChaned_Hour_AttachDP == true)
                {
                    if (e.NewValue == null)
                        selector.SetText_Hour("");
                    else if (e.NewValue.GetType().Equals(typeof(int)))
                    {
                        selector.SetText_Hour(int.Parse(e.NewValue.ToString()).ToString());
                    }
                    else
                    {
                        selector.SetText_Hour("0");
                    }
                }
            }
            #endregion
            #region Minutes
            public int Minutes
            {
                get { return (int)GetValue(MinutesProperty); }
                set { SetValue(MinutesProperty, value); }
            }
            public static readonly DependencyProperty MinutesProperty =
                DependencyProperty.Register("Minutes", typeof(int), typeof(TimeSpanBox), new PropertyMetadata(0, On_Minute_CHanged));
    
            private static void On_Minute_CHanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                TimeSpanBox selector = d as TimeSpanBox;
                if (selector != null && selector.CanRaiseTxtChaned_Minute_AttachDP == true)
                {
                    if (e.NewValue == null)
                        selector.SetText_Minute("");
                    else if (e.NewValue.GetType().Equals(typeof(int)))
                    {
                        selector.SetText_Minute(int.Parse(e.NewValue.ToString()).ToString());
                    }
                    else
                    {
                        selector.SetText_Minute("0");
                    }
                }
            }
            #endregion
            #region Secound
            public int Secound
            {
                get { return (int)GetValue(SecoundProperty); }
                set { SetValue(SecoundProperty, value); }
            }
            public static readonly DependencyProperty SecoundProperty =
                DependencyProperty.Register("Secound", typeof(int), typeof(TimeSpanBox), new PropertyMetadata(0, On_Secound_Changed));
    
            private static void On_Secound_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                TimeSpanBox selector = d as TimeSpanBox;
                if (selector != null && selector.CanRaiseTxtChaned_Secound_AttachDP == true)
                {
                    if (e.NewValue == null)
                        selector.SetText_Secound("");
                    else if (e.NewValue.GetType().Equals(typeof(int)))
                    {
                        selector.SetText_Secound(int.Parse(e.NewValue.ToString()).ToString());
                    }
                    else
                    {
                        selector.SetText_Secound("0");
                    }
                }
            }
            #endregion
    
            #region 文本
            public string YearText
            {
                get { return (string)GetValue(YearTextProperty); }
                set { SetValue(YearTextProperty, value); }
            }
            public static readonly DependencyProperty YearTextProperty =
                DependencyProperty.Register("YearText", typeof(string), typeof(TimeSpanBox), new PropertyMetadata("0"));
    
    
            public string MonthText
            {
                get { return (string)GetValue(MonthTextProperty); }
                set { SetValue(MonthTextProperty, value); }
            }
            public static readonly DependencyProperty MonthTextProperty =
                DependencyProperty.Register("MonthText", typeof(string), typeof(TimeSpanBox), new PropertyMetadata("0"));
    
    
            public string DayText
            {
                get { return (string)GetValue(DayTextProperty); }
                set { SetValue(DayTextProperty, value); }
            }
            public static readonly DependencyProperty DayTextProperty =
                DependencyProperty.Register("DayText", typeof(string), typeof(TimeSpanBox), new PropertyMetadata("0"));
    
    
            public string HourText
            {
                get { return (string)GetValue(HourTextProperty); }
                set { SetValue(HourTextProperty, value); }
            }
            public static readonly DependencyProperty HourTextProperty =
                DependencyProperty.Register("HourText", typeof(string), typeof(TimeSpanBox), new PropertyMetadata("0"));
    
    
            public string MinuteText
            {
                get { return (string)GetValue(MinuteTextProperty); }
                set { SetValue(MinuteTextProperty, value); }
            }
            public static readonly DependencyProperty MinuteTextProperty =
                DependencyProperty.Register("MinuteText", typeof(string), typeof(TimeSpanBox), new PropertyMetadata("0"));
    
            public string SecoundText
            {
                get { return (string)GetValue(SecoundTextProperty); }
                set { SetValue(SecoundTextProperty, value); }
            }
            public static readonly DependencyProperty SecoundTextProperty =
                DependencyProperty.Register("SecoundText", typeof(string), typeof(TimeSpanBox), new PropertyMetadata("0"));
            #endregion
    
            #region UpDownBtnVisible
            public Visibility UpDownBtnVisible
            {
                get { return (Visibility)GetValue(UpDownBtnVisibleProperty); }
                set { SetValue(UpDownBtnVisibleProperty, value); }
            }
            public static readonly DependencyProperty UpDownBtnVisibleProperty =
                DependencyProperty.Register("UpDownBtnVisible", typeof(Visibility), typeof(TimeSpanBox), new PropertyMetadata(Visibility.Collapsed, OnUpDownBtnVisible_Changed));
    
            private static void OnUpDownBtnVisible_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                TimeSpanBox selector = d as TimeSpanBox;
                if (selector != null)
                {
                    selector.gridShow.Visibility = e.NewValue != null && e.NewValue is Visibility && (Visibility)e.NewValue == Visibility.Visible
                        ? Visibility.Visible
                        : Visibility.Collapsed;
                }
            }
            #endregion
    
            #region 标题颜色
            public Brush TitleBrush
            {
                get { return (Brush)GetValue(TitleBrushProperty); }
                set { SetValue(TitleBrushProperty, value); }
            }
    
            // Using a DependencyProperty as the backing store for TitleBrush.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty TitleBrushProperty =
                DependencyProperty.Register("TitleBrush", typeof(Brush), typeof(TimeSpanBox), new PropertyMetadata(new SolidColorBrush(Colors.Black), on_TitleBrush_CHanged));
    
            private static void on_TitleBrush_CHanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                TimeSpanBox sender = d as TimeSpanBox;
                if (sender != null && e.NewValue != null && e.NewValue is Brush)
                {
                    Brush newBrush = ((Brush)e.NewValue);
                    sender.txtbYear.Foreground = newBrush;
                    sender.txtbMonth.Foreground = newBrush;
                    sender.txtbDay.Foreground = newBrush;
                    sender.txtbMinute.Foreground = newBrush;
                    sender.txtbHour.Foreground = newBrush;
                    sender.txtbSecound.Foreground = newBrush;
                }
                else if (e.NewValue != null || !(e.NewValue is Brush))
                {
                    sender.txtbYear.Foreground = new SolidColorBrush(Colors.Black);
                    sender.txtbMonth.Foreground = new SolidColorBrush(Colors.Black);
                    sender.txtbDay.Foreground = new SolidColorBrush(Colors.Black);
                    sender.txtbMinute.Foreground = new SolidColorBrush(Colors.Black);
                    sender.txtbHour.Foreground = new SolidColorBrush(Colors.Black);
                    sender.txtbSecound.Foreground = new SolidColorBrush(Colors.Black);
                }
            }
            #endregion
    
        }
    }

    如何使用:

            xmlns:local="clr-namespace:TimeEditerDemo"
    ....
    
    
    
                <!--不显示年,不现实月,不显示秒,显示按钮,天时分红字,-->
                <local:TimeSpanBox x:Name="pick" Height="25" TitleBrush="Red"
                        IsYearVisible="False" IsMonthVisible="False" IsSecoundVisible="False" UpDownBtnVisible="Visible"/>
                <TextBox x:Name="inputNum"/>
                <Button Content="Set Year" Click="Button_Click"/>
                <TextBlock Margin="0 10 0 0">
                    <Run Text="当前时间:"/>
                    <Run Text="{Binding Year,ElementName=pick}"/>
                    <Run Text="年"/>
                      <Run Text="{Binding Month,ElementName=pick}"/>
                    <Run Text="月"/>
                      <Run Text="{Binding Day,ElementName=pick}"/>
                    <Run Text="日"/>
                      <Run Text="{Binding Hour,ElementName=pick}"/>
                    <Run Text="时"/>
                      <Run Text="{Binding Minutes,ElementName=pick}"/>
                    <Run Text="分"/>
                      <Run Text="{Binding Secound,ElementName=pick}"/>
                    <Run Text="秒"/>
                </TextBlock>
    
                <x:Code>
                    private void Button_Click(object sender, RoutedEventArgs e)
                    {
                        int tempValue = 0;
                        pick.Day = int.TryParse(this.inputNum.Text, out tempValue) ? tempValue : 0;
                    }
                </x:Code>

    上述控件待完善: 给 Year、Month、Day、Hour、Minite、Secound、负值的时候的CoerceValueCallback

    缺少对应的Year_Change  Month_Change Day_Change Hour_CHange Minite_Change Secound_Chang 等事件

    //本人懒的弄了,UI也没有任何优化

    运行结果

     Bug Fix 初始化时设置时分秒后显示值为0

    原因: UserControl 种的Initial事件种如果包含的BInding是Relative,不能及时更新对应的绑定源,如下

    <TextBox Grid.Column="0" BorderBrush="Transparent" BorderThickness="0" x:Name="txtYear" VerticalContentAlignment="Center"
                     InputMethod.IsInputMethodEnabled="False" TextAlignment="Right" Padding="0,0,1,0"
                     Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:TimeSpanBox},Path=YearText,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
  • 相关阅读:
    大数据概述
    递归下降语法分析
    消除左递归c语言文法
    自动转换机
    简单的C语言文法
    实验报告一 词法分析程序
    组合数据类型练习
    Python绘制五星红旗
    熟悉常用Linux操作
    大数据概述
  • 原文地址:https://www.cnblogs.com/wandia/p/13953466.html
Copyright © 2020-2023  润新知