前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >WPF 日期选择器和时间选择器

WPF 日期选择器和时间选择器

作者头像
码客说
发布2023-02-10 14:37:15
5.8K0
发布2023-02-10 14:37:15
举报
文章被收录于专栏:码客码客

前言

WPF中自带的有日期选择器,但是没有时间选择器。

日期和字符串互相转换

日期转字符串

代码语言:javascript
复制
DateTime dateTime = DateTime.Now;
string timeStr = dateTime.ToString("yyyy-MM-dd hh:mm:ss");
Console.WriteLine(timeStr);

方式2

代码语言:javascript
复制
string.Format("yyyy-MM-dd", DateTime.Now);

字符串转日期

直接转换

格式有要求,必须是yyyy-MM-dd hh:mm:ss或者yyyy/MM/dd hh:mm:ss

代码语言:javascript
复制
DateTime dateTime2 = Convert.ToDateTime(timeStr);
Console.WriteLine(dateTime2.ToString());

示例2

代码语言:javascript
复制
DateTime dateTime2 = Convert.ToDateTime("2011/05/26 10:30");
Console.WriteLine(dateTime2.ToString());

指定格式

代码语言:javascript
复制
DateTimeFormatInfo dtFormat = new System.Globalization.DateTimeFormatInfo();
dtFormat.ShortDatePattern = "yyyy/MM/dd";
DateTime dt = Convert.ToDateTime("2011/05/26 10:30", dtFormat);
Console.WriteLine(dt.ToString());

时间也指定

代码语言:javascript
复制
DateTimeFormatInfo dtFormat = new System.Globalization.DateTimeFormatInfo();
dtFormat.ShortDatePattern = "yyyy/MM/dd";
dtFormat.ShortTimePattern = "hh:mm:ss";
DateTime dt = Convert.ToDateTime("2011/05/26 10:30", dtFormat);
Console.WriteLine(dt.ToString());

日期选择器

基本使用

代码语言:javascript
复制
<DatePicker BorderBrush="#f0f0f0" />

设置默认日期和回调

代码语言:javascript
复制
<DatePicker
                  Name="reportDatePicker"
                  Grid.Row="1"
                  Grid.Column="1"
                  Margin="0,0,10,0"
                  BorderBrush="#f0f0f0"
                  SelectedDateChanged="DatePicker_SelectedDateChanged" />

代码中

代码语言:javascript
复制
reportDatePicker.SelectedDate = DateTime.Now;

事件回调

代码语言:javascript
复制
private void DatePicker_SelectedDateChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
  DatePicker dp = (DatePicker)sender;
  Console.WriteLine(dp.SelectedDate.ToString());
}

设置禁止选择的日期

代码语言:javascript
复制
<DatePicker BorderBrush="#f0f0f0">
  <DatePicker.BlackoutDates>
    <CalendarDateRange End="2/10/2023" Start="2/5/2023" />
    <CalendarDateRange End="2/20/2023" Start="2/15/2023" />
  </DatePicker.BlackoutDates>
</DatePicker>

时间选择器

基本使用

代码语言:javascript
复制
<local:TimePicker x:Name="reportTimePicker"/>

设置值

代码语言:javascript
复制
reportTimePicker.Hour = 23;
reportTimePicker.Minute = 30;
reportTimePicker.Second = 0;

获取值

代码语言:javascript
复制
Console.WriteLine("Hour:" + reportTimePicker.Hour);
Console.WriteLine("Minute:" + reportTimePicker.Minute);
Console.WriteLine("Second:" + reportTimePicker.Second);

双向绑定

代码语言:javascript
复制
<local:TimeEditer 
                  Hour="{Binding Hour,Mode=TwoWay}" 
                  Minute="{Binding Minute,Mode=TwoWay}" 
                  Second="{Binding Seccond,Mode=TwoWay}" 
                  Width="90" Height="30" HorizontalAlignment="Left"/>

组件代码

TimePicker.cs

代码语言:javascript
复制
using System;
using System.Timers;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

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

        private TextBox currentTextBox;
        private Button btnUp;
        private Button btnDown;
        private TextBox txt1;
        private TextBox txt2;
        private TextBox txt3;
        private TextBox txt4;

        public TimePicker()
        {
            var newTime = DateTime.Now.AddMinutes(5);
            Hour = newTime.Hour;
            Minute = newTime.Minute;
            Second = newTime.Second;
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            btnUp = Template.FindName("PART_UP", this) as Button;
            btnDown = Template.FindName("PART_DOWN", this) as Button;
            txt1 = Template.FindName("PART_TXTHOUR", this) as TextBox;
            txt2 = Template.FindName("PART_TXTMINUTE", this) as TextBox;
            txt3 = Template.FindName("PART_TXTSECOND", this) as TextBox;
            txt4 = Template.FindName("PART_TXT4", this) as TextBox;

            txt1.GotFocus += TextBox_GotFocus;
            txt2.GotFocus += TextBox_GotFocus;
            txt3.GotFocus += TextBox_GotFocus;
            txt1.LostFocus += TextBox_LostFocus;
            txt2.LostFocus += TextBox_LostFocus;
            txt3.LostFocus += TextBox_LostFocus;
            txt1.KeyDown += Txt1_KeyDown;
            txt2.KeyDown += Txt1_KeyDown;
            txt3.KeyDown += Txt1_KeyDown;

            txt4.GotFocus += TextBox2_GotFocus;
            txt4.LostFocus += TextBox2_LostFocus;

            this.GotFocus += UserControl_GotFocus;
            this.LostFocus += UserControl_LostFocus;

            this.Repeater(btnUp, (t, num, reset) =>
            {
                if (reset && t.Interval == 500)
                    t.Interval = 50;
                Dispatcher.Invoke(
                    new Action(() =>
                {
                    if (currentTextBox.Name == "PART_TXTHOUR")
                    {
                        int.TryParse(currentTextBox.Text, out int numResult);
                        numResult += num;
                        if (numResult >= 24)
                            numResult = 0;
                        if (numResult < 0)
                            numResult = 23;
                        currentTextBox.Text = numResult.ToString("00");
                    }
                    else if (currentTextBox.Name == "PART_TXTMINUTE")
                    {
                        int.TryParse(currentTextBox.Text, out int numResult);
                        numResult += num;
                        if (numResult >= 60)
                            numResult = 0;
                        if (numResult < 0)
                            numResult = 59;
                        currentTextBox.Text = numResult.ToString("00");
                    }
                    else if (currentTextBox.Name == "PART_TXTSECOND")
                    {
                        int.TryParse(currentTextBox.Text, out int numResult);
                        numResult += num;
                        if (numResult >= 60)
                            numResult = 0;
                        if (numResult < 0)
                            numResult = 59;
                        currentTextBox.Text = numResult.ToString("00");
                    }
                }));
            }, 1);
            this.Repeater(btnDown, (t, num, reset) =>
            {
                if (reset && t.Interval == 500)
                    t.Interval = 50;
                Dispatcher.Invoke(new Action(() =>
                {
                    if (currentTextBox.Name == "PART_TXTHOUR")
                    {
                        int.TryParse(currentTextBox.Text, out int numResult);
                        numResult += num;
                        if (numResult >= 24)
                            numResult = 0;
                        if (numResult < 0)
                            numResult = 23;
                        currentTextBox.Text = numResult.ToString("00");
                    }
                    else if (currentTextBox.Name == "PART_TXTMINUTE")
                    {
                        int.TryParse(currentTextBox.Text, out int numResult);
                        numResult += num;
                        if (numResult >= 60)
                            numResult = 0;
                        if (numResult < 0)
                            numResult = 59;
                        currentTextBox.Text = numResult.ToString("00");
                    }
                    else if (currentTextBox.Name == "PART_TXTSECOND")
                    {
                        int.TryParse(currentTextBox.Text, out int numResult);
                        numResult += num;
                        if (numResult >= 60)
                            numResult = 0;
                        if (numResult < 0)
                            numResult = 59;
                        currentTextBox.Text = numResult.ToString("00");
                    }
                }));
            }, -1);
        }

        private void TextBox_GotFocus(object sender, RoutedEventArgs e)
        {
            var textBox = sender as TextBox;
            textBox.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#0078d7"));
            textBox.Foreground = new SolidColorBrush(Colors.White);
            currentTextBox = textBox;
        }

        private void TextBox_LostFocus(object sender, RoutedEventArgs e)
        {
            var textBox = sender as TextBox;
            textBox.Background = new SolidColorBrush(Colors.Transparent);
            textBox.Foreground = new SolidColorBrush(Colors.Black);
            int.TryParse(currentTextBox.Text, out int numResult);
            currentTextBox.Text = numResult.ToString("00");
        }

        private void UserControl_LostFocus(object sender, RoutedEventArgs e)
        {
            this.BorderBrush = new SolidColorBrush(Color.FromArgb(255, 234, 234, 234));
            NumIncreaseVisible = Visibility.Collapsed;
        }

        private void UserControl_GotFocus(object sender, RoutedEventArgs e)
        {
            this.BorderBrush = new SolidColorBrush(Color.FromArgb(255, 0, 120, 215));
            NumIncreaseVisible = Visibility.Visible;
        }

        private void TextBox2_GotFocus(object sender, RoutedEventArgs e)
        {
            txt3.Focus();
        }

        private void TextBox2_LostFocus(object sender, RoutedEventArgs e)
        {
        }

        public void Repeater(Button btn, Action<Timer, int, bool> callBack, int num, int interval = 500)
        {
            var timer = new Timer { Interval = interval };
            timer.Elapsed += (sender, e) =>
            {
                callBack?.Invoke(timer, num, true);
            };
            btn.PreviewMouseLeftButtonDown += (sender, e) =>
            {
                callBack?.Invoke(timer, num, false);
                timer.Start();
            };
            btn.PreviewMouseLeftButtonUp += (sender, e) =>
            {
                timer.Interval = 500;
                timer.Stop();
            };
        }

        private void Txt1_KeyDown(object sender, KeyEventArgs e)
        {
            int.TryParse(currentTextBox.Text, out int numResult);

            if ((int)e.Key >= 34 && (int)e.Key <= 43)
            {
                if (currentTextBox.Text.Length == 1)
                {
                    int.TryParse(currentTextBox.Text + ((int)e.Key - 34).ToString(), out int preNumResult);
                    if (currentTextBox.Name == "PART_TXTHOUR")
                    {
                        if (preNumResult >= 24)
                        {
                            return;
                        }
                    }
                    else if (currentTextBox.Name == "PART_TXTMINUTE")
                    {
                        if (preNumResult >= 60)
                        {
                            return;
                        }
                    }
                    else if (currentTextBox.Name == "PART_TXTSECOND")
                    {
                        if (preNumResult >= 60)
                        {
                            return;
                        }
                    }

                    currentTextBox.Text += ((int)e.Key - 34).ToString();
                }
                else
                {
                    currentTextBox.Text = ((int)e.Key - 34).ToString();
                }
            }

            if ((int)e.Key >= 74 && (int)e.Key <= 83)
            {
                if (currentTextBox.Text.Length == 1)
                {
                    int.TryParse(currentTextBox.Text + ((int)e.Key - 74).ToString(), out int preNumResult);
                    if (currentTextBox.Name == "PART_TXTHOUR")
                    {
                        if (preNumResult >= 24)
                        {
                            return;
                        }
                    }
                    else if (currentTextBox.Name == "PART_TXTMINUTE")
                    {
                        if (preNumResult >= 60)
                        {
                            return;
                        }
                    }
                    else if (currentTextBox.Name == "PART_TXTSECOND")
                    {
                        if (preNumResult >= 60)
                        {
                            return;
                        }
                    }
                    currentTextBox.Text += ((int)e.Key - 74).ToString();
                }
                else
                {
                    currentTextBox.Text = ((int)e.Key - 74).ToString();
                }
            }
        }

        public int Hour
        {
            get { return (int)GetValue(HourProperty); }
            set { SetValue(HourProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Hour.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty HourProperty =
            DependencyProperty.Register("Hour", typeof(int), typeof(TimePicker), new PropertyMetadata(DateTime.Now.Hour));

        public int Minute
        {
            get { return (int)GetValue(MinuteProperty); }
            set { SetValue(MinuteProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Minute.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MinuteProperty =
            DependencyProperty.Register("Minute", typeof(int), typeof(TimePicker), new PropertyMetadata(DateTime.Now.Minute));

        public int Second
        {
            get { return (int)GetValue(SecondProperty); }
            set { SetValue(SecondProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Second.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SecondProperty =
            DependencyProperty.Register("Second", typeof(int), typeof(TimePicker), new PropertyMetadata(DateTime.Now.Second));

        public Visibility NumIncreaseVisible
        {
            get { return (Visibility)GetValue(NumIncreaseVisibleProperty); }
            set { SetValue(NumIncreaseVisibleProperty, value); }
        }

        // Using a DependencyProperty as the backing store for NumIncreaseVisible.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty NumIncreaseVisibleProperty =
            DependencyProperty.Register("NumIncreaseVisible", typeof(Visibility), typeof(TimePicker), new PropertyMetadata(Visibility.Collapsed));
    }
}

样式文件

StyleTimePicker.xaml

代码语言:javascript
复制
<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:ZView">

    <Style TargetType="{x:Type local:TimePicker}">
        <Setter Property="BorderThickness" Value="1" />
        <Setter Property="BorderBrush" Value="#ececec" />
        <Setter Property="Hour" Value="00" />
        <Setter Property="Minute" Value="00" />
        <Setter Property="Second" Value="00" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:TimePicker}">
                    <Border
                        Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                        <Grid Margin="0,0">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="18" />
                                <ColumnDefinition Width="auto" />
                                <ColumnDefinition Width="18" />
                                <ColumnDefinition Width="auto" />
                                <ColumnDefinition Width="18" />
                                <ColumnDefinition Width="*" />
                            </Grid.ColumnDefinitions>
                            <TextBox
                                x:Name="PART_TXTHOUR"
                                VerticalAlignment="Center"
                                HorizontalContentAlignment="Center"
                                AutoWordSelection="False"
                                BorderThickness="0"
                                Cursor="Arrow"
                                Focusable="True"
                                Foreground="Black"
                                IsReadOnly="True"
                                IsReadOnlyCaretVisible="False"
                                SelectionBrush="White"
                                Text="{Binding Hour, RelativeSource={RelativeSource TemplatedParent}, StringFormat={}{0:00}, UpdateSourceTrigger=PropertyChanged}" />
                            <TextBlock
                                Grid.Column="1"
                                VerticalAlignment="Center"
                                Text=":" />
                            <TextBox
                                x:Name="PART_TXTMINUTE"
                                Grid.Column="2"
                                VerticalAlignment="Center"
                                HorizontalContentAlignment="Center"
                                AutoWordSelection="False"
                                BorderThickness="0"
                                Cursor="Arrow"
                                Focusable="True"
                                Foreground="Black"
                                IsReadOnly="True"
                                IsReadOnlyCaretVisible="False"
                                Text="{Binding Minute, RelativeSource={RelativeSource TemplatedParent}, StringFormat={}{0:00}, UpdateSourceTrigger=PropertyChanged}" />
                            <TextBlock
                                Grid.Column="3"
                                VerticalAlignment="Center"
                                Text=":" />
                            <TextBox
                                x:Name="PART_TXTSECOND"
                                Grid.Column="4"
                                VerticalAlignment="Center"
                                HorizontalContentAlignment="Center"
                                AutoWordSelection="False"
                                BorderThickness="0"
                                Cursor="Arrow"
                                Focusable="True"
                                Foreground="Black"
                                IsReadOnly="True"
                                IsReadOnlyCaretVisible="False"
                                Text="{Binding Second, RelativeSource={RelativeSource TemplatedParent}, StringFormat={}{0:00}, UpdateSourceTrigger=PropertyChanged}" />
                            <TextBox
                                x:Name="PART_TXT4"
                                Grid.Column="5"
                                AutoWordSelection="False"
                                Background="Transparent"
                                BorderThickness="0"
                                Cursor="Arrow"
                                IsReadOnly="True"
                                IsReadOnlyCaretVisible="False" />

                            <Grid
                                x:Name="numIncrease"
                                Grid.Column="5"
                                HorizontalAlignment="Right"
                                Visibility="{TemplateBinding NumIncreaseVisible}">
                                <Grid.RowDefinitions>
                                    <RowDefinition />
                                    <RowDefinition />
                                </Grid.RowDefinitions>
                                <Button
                                    x:Name="PART_UP"
                                    Width="17"
                                    Height="11"
                                    VerticalAlignment="Bottom"
                                    Focusable="False">

                                    <Image Source="pack://application:,,,/Images/TimeEditer/arrowTop.png" />
                                </Button>
                                <Button
                                    x:Name="PART_DOWN"
                                    Grid.Row="1"
                                    Width="17"
                                    Height="11"
                                    VerticalAlignment="Top"
                                    Focusable="False">
                                    <Image Source="pack://application:,,,/Images/TimeEditer/arrowBottom.png" />
                                </Button>
                            </Grid>
                        </Grid>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-02-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 日期和字符串互相转换
    • 日期转字符串
      • 字符串转日期
        • 直接转换
        • 指定格式
    • 日期选择器
      • 基本使用
        • 设置默认日期和回调
          • 设置禁止选择的日期
          • 时间选择器
            • 基本使用
              • 双向绑定
                • 组件代码
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档