.NET6 WPF DateTime用户控件-DateTimePicker

一.直接上效果

二.Nuget包

日历、时钟是用的是MaterialDesignThemes的组件,需要安装Nuget包MaterialDesignThemes

三.代码

前台:

<UserControl x:Class="BSDS.DateTimePicker"
             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:md="http://materialdesigninxaml.net/winfx/xaml/themes"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <md:DialogHost DialogTheme="Inherit" Identifier="DateTimePicker">
        <DockPanel>
            <Grid>
                <StackPanel
                Orientation="Horizontal">
                    <TextBox
                        VerticalAlignment="Center"
                        VerticalContentAlignment="Center" x:Name="TextShow"
                        FontSize="{Binding TextBoxFontSize,Mode=TwoWay,RelativeSource={RelativeSource AncestorType=UserControl}}" 
                        Width="{Binding TextBoxWidth,Mode=TwoWay,RelativeSource={RelativeSource AncestorType=UserControl}}"
                        Height="{Binding TextBoxHeight,Mode=TwoWay,RelativeSource={RelativeSource AncestorType=UserControl}}"
                        BorderBrush="MediumSeaGreen" BorderThickness="0.5"
                        Text="{Binding Text,Mode=TwoWay,RelativeSource={RelativeSource AncestorType=UserControl}}" 
                        />
                    <Button
                        Margin="3,0,0,0" Height="{Binding TextBoxHeight,Mode=TwoWay,RelativeSource={RelativeSource AncestorType=UserControl}}"
                        Command="{x:Static md:DialogHost.OpenDialogCommand}"
                        Content="...">
                        <Button.CommandParameter>
                            <Grid 
                                    Margin="-1">
                                <Grid.RowDefinitions>
                                    <RowDefinition
                                Height="*" />
                                    <RowDefinition
                                Height="Auto" />
                                </Grid.RowDefinitions>
                                <StackPanel
                                Height="420"
                                Width="600"
                                Grid.Row="0"
                                Orientation="Horizontal">   
                                    <Calendar
                                        x:Name="CombinedCalendar"
                                        Margin="-1,-4,-1,0" />
                                    <md:Clock 
                                        FontSize="15"
                                    x:Name="CombinedClock"
                                    DisplayAutomation="CycleWithSeconds"
                                    Is24Hours="True" />
                                </StackPanel>
                                <StackPanel
                                    Grid.Row="1"
                                    Margin="8,-30,8,8"
                                    HorizontalAlignment="Right"
                                    Orientation="Horizontal">
                                    <Button
                                    Command="{x:Static md:DialogHost.CloseDialogCommand}"
                                        CommandParameter="0"
                                        Content="取消"
                                        Style="{StaticResource MaterialDesignFlatButton}" />
                                    <Button
                                    Content="重置"
                                    Click="Reset"
                                    Style="{StaticResource MaterialDesignFlatButton}" />
                                    <Button
                                        Command="{x:Static md:DialogHost.CloseDialogCommand}"
                                        CommandParameter="1"
                                        Content="确定"
                                        Click="OK"
                                        Style="{StaticResource MaterialDesignFlatButton}" />
                                </StackPanel>
                            </Grid>
                        </Button.CommandParameter>
                    </Button>
                </StackPanel>
            </Grid>
        </DockPanel>
    </md:DialogHost>
</UserControl>

后台:

using System.Windows;
using System.Windows.Controls;

namespace BSDS
{
    /// <summary>
    /// DateTimePicker.xaml 的交互逻辑
    /// </summary>
    public partial class DateTimePicker : UserControl
    {
        public DateTimePicker()
        {
            InitializeComponent();
            CombinedCalendar.SelectedDate = DateTime.Now;
            CombinedClock.Time = DateTime.Now;
           (Content as FrameworkElement)!.DataContext = this;
        }
        private bool isUIChangeText;
        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register("Text", typeof(string), typeof(DateTimePicker),
                new PropertyMetadata(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), (s, e) =>
                {
                    if (s is DateTimePicker dp && dp.isUIChangeText)
                    {
                        if (DateTime.TryParse(dp.Text, out DateTime dateTime))
                        {
                            dp.CombinedCalendar.SelectedDate = 
                            dp.CombinedClock.Time = dp.DateTime = dateTime;
                            if (dp.Text != dateTime.ToString("yyyy-MM-dd HH:mm:ss"))
                            {
                                dp.isUIChangeText = false;
                                dp.Text = dateTime.ToString("yyyy-MM-dd HH:mm:ss");
                                dp.isUIChangeText = true;
                            }
                        }
                        else
                        {
                            dp.isUIChangeText = false;
                            dp.Text = dp.DateTime.ToString("yyyy-MM-dd HH:mm:ss");
                            dp.isUIChangeText = true;
                        }
                    }
                }));
        public string Text
        {
            get => (string)GetValue(TextProperty);
            set => SetValue(TextProperty, value);
        }
        public static readonly DependencyProperty DateTimeProperty =
            DependencyProperty.Register("DateTime", typeof(DateTime), typeof(DateTimePicker),
                new PropertyMetadata(DateTime.Now, (s, e) =>
                {
                    if (s is DateTimePicker dp)
                    {
                        dp.CombinedCalendar.SelectedDate = dp.CombinedClock.Time = dp.DateTime;
                        dp.isUIChangeText = false;
                        dp.Text = dp.DateTime.ToString("yyyy-MM-dd HH:mm:ss");
                        dp.isUIChangeText = true;
                    }
                }));
        public DateTime DateTime
        {
            get => (DateTime)GetValue(DateTimeProperty);
            set => SetValue(DateTimeProperty, value);
        }
        public static readonly DependencyProperty TextBoxFontSizeProperty = 
            DependencyProperty.Register("TextBoxFontSize", typeof(double), typeof(DateTimePicker),
                new PropertyMetadata((double)12));
        public double TextBoxFontSize
        {
            get => (double)GetValue(TextBoxFontSizeProperty);
            set => SetValue(TextBoxFontSizeProperty, value);
        }
        public static readonly DependencyProperty TextBoxWidthProperty =
            DependencyProperty.Register("TextBoxWidth", typeof(double), typeof(DateTimePicker),
                new PropertyMetadata((double)120));
        public double TextBoxWidth
        {
            get => (double)GetValue(TextBoxWidthProperty);
            set => SetValue(TextBoxWidthProperty, value);
        }
        public static readonly DependencyProperty TextBoxHeightProperty =
            DependencyProperty.Register("TextBoxHeight", typeof(double), typeof(DateTimePicker),
                new PropertyMetadata((double)30));
        public double TextBoxHeight
        {
            get => (double)GetValue(TextBoxHeightProperty);
            set => SetValue(TextBoxHeightProperty, value);
        }
        private void OK(object sender, RoutedEventArgs e)
        {
            
            string Date = ((DateTime)CombinedCalendar.SelectedDate!).ToString("yyyy-MM-dd");
            string Time = CombinedClock.Time.ToString("HH:mm:ss");
            DateTime = DateTime.Parse($"{Date} {Time}");
        }

        private void Reset(object sender, RoutedEventArgs e)
        {
            CombinedCalendar.SelectedDate = CombinedClock.Time = DateTime.Now;
        }
    }
}

四.使用例子

xmlns:self="clr-namespace:BSDS"//xaml引入用户控件所在的程序集(此处是本地BSDS项目下)

<self:DateTimePicker DateTime="{Binding EndTime,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
            Margin="0,10,0,0" VerticalAlignment="Center"/>

WPF中,可以使用数据模板和数据绑定机制来根据结构体属性自动生成控件。具体来说,可以为结构体定义一个数据模板,用于描述结构体的属性应该如何呈现为控件,并将结构体的实例作为数据上下文设置到该数据模板中,这样WPF就会自动根据数据模板生成对应的控件。 假设我们有一个包含三个属性的结构体Person,如下所示: ```csharp public struct Person { public string Name { get; set; } public int Age { get; set; } public bool IsMale { get; set; } } ``` 现在,我们想要根据这个结构体的属性自动生成控件,可以使用以下代码定义一个数据模板: ```xml <DataTemplate DataType="{x:Type local:Person}"> <StackPanel> <TextBlock Text="Name:"/> <TextBox Text="{Binding Path=Name, Mode=TwoWay}"/> <TextBlock Text="Age:"/> <TextBox Text="{Binding Path=Age, Mode=TwoWay}"/> <TextBlock Text="Is Male:"/> <CheckBox IsChecked="{Binding Path=IsMale, Mode=TwoWay}"/> </StackPanel> </DataTemplate> ``` 然后,在代码中,我们需要将Person结构体的实例作为数据上下文设置到该数据模板中,以便WPF能够根据数据模板自动生成控件。假设我们有一个名为person的Person结构体变量,可以使用以下代码将它设置为数据上下文: ```csharp ContentControl contentControl = new ContentControl(); contentControl.Content = person; contentControl.ContentTemplate = FindResource(typeof(Person)) as DataTemplate; ``` 这样,WPF就会根据数据模板自动生成一个包含三个TextBox控件和一个CheckBox控件的StackPanel控件,用于显示和修改Person结构体的属性。当用户在界面中修改Name、Age或IsMale属性时,Person结构体中的相应属性值也会自动更新。反之,当Person结构体中的属性值发生变化时,界面中显示这些属性的控件的值也会自动更新。 需要注意的是,为了实现自动更新,必须将数据绑定的Mode属性设置为TwoWay,这样绑定才能够在控件的值发生变化时更新数据源。另外,如果Person结构体中的属性发生变化时,界面中的控件没有自动更新,可以使用INotifyPropertyChanged接口来通知界面更新控件的值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值