C#教程

关注公众号 jb51net

关闭
首页 > 软件编程 > C#教程 > WPF时间选择控件

基于WPF实现时间选择控件

作者:WPF开发者

这篇文章主要介绍了如何基于WPF实现简单的时间选择控件,文中的示例代码讲解详细,对我们的学习或工作有一定帮助,需要的小伙伴可以参考一下

WPF 实现时间选择控件

实现代码

1)代码TimePicker.cs如下:

using System;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;

namespace WPFDevelopers.Controls
{
    [TemplatePart(Name = TimeSelectorTemplateName, Type = typeof(ListBox))]
    [TemplatePart(Name = EditableTextBoxTemplateName, Type = typeof(TextBox))]
    [TemplatePart(Name = PopupTemplateName, Type = typeof(Popup))]
    public class TimePicker : Control
    {
        private const string TimeSelectorTemplateName = "PART_TimeSelector";
        private const string EditableTextBoxTemplateName = "PART_EditableTextBox";
        private const string PopupTemplateName = "PART_Popup";

        public static readonly DependencyProperty SelectedTimeFormatProperty =
            DependencyProperty.Register("SelectedTimeFormat", typeof(string), typeof(TimePicker),
                new PropertyMetadata("HH:mm:ss"));

        public static readonly DependencyProperty MaxDropDownHeightProperty =
            DependencyProperty.Register("MaxDropDownHeight", typeof(double), typeof(TimePicker),
                new UIPropertyMetadata(SystemParameters.PrimaryScreenHeight / 3.0, OnMaxDropDownHeightChanged));

        public static readonly DependencyProperty SelectedTimeProperty =
            DependencyProperty.Register("SelectedTime", typeof(DateTime?), typeof(TimePicker),
                new PropertyMetadata(null, OnSelectedTimeChanged));

        public static readonly DependencyProperty IsCurrentTimeProperty =
            DependencyProperty.Register("IsCurrentTime", typeof(bool), typeof(TimePicker), new PropertyMetadata(false));

        private DateTime _date;
        private Popup _popup;
        private TextBox _textBox;
        private TimeSelector _timeSelector;

        static TimePicker()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(TimePicker),
                new FrameworkPropertyMetadata(typeof(TimePicker)));
        }

        public string SelectedTimeFormat
        {
            get => (string) GetValue(SelectedTimeFormatProperty);
            set => SetValue(SelectedTimeFormatProperty, value);
        }

        public DateTime? SelectedTime
        {
            get => (DateTime?) GetValue(SelectedTimeProperty);
            set => SetValue(SelectedTimeProperty, value);
        }

        public bool IsCurrentTime
        {
            get => (bool) GetValue(IsCurrentTimeProperty);
            set => SetValue(IsCurrentTimeProperty, value);
        }

        private static void OnMaxDropDownHeightChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var ctrl = d as TimePicker;
            if (ctrl != null)
                ctrl.OnMaxDropDownHeightChanged((double) e.OldValue, (double) e.NewValue);
        }

        protected virtual void OnMaxDropDownHeightChanged(double oldValue, double newValue)
        {
        }

        private static void OnSelectedTimeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var ctrl = d as TimePicker;
            if (ctrl != null && e.NewValue != null)
            {
                var dateTime = (DateTime) e.NewValue;
                if (ctrl._timeSelector != null && dateTime > DateTime.MinValue)
                    ctrl._timeSelector.SelectedTime = dateTime;
                else
                    ctrl._date = dateTime;
            }
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            _textBox = GetTemplateChild(EditableTextBoxTemplateName) as TextBox;
            _timeSelector = GetTemplateChild(TimeSelectorTemplateName) as TimeSelector;
            if (_timeSelector != null)
            {
                _timeSelector.SelectedTimeChanged -= TimeSelector_SelectedTimeChanged;
                _timeSelector.SelectedTimeChanged += TimeSelector_SelectedTimeChanged;
                if (!SelectedTime.HasValue && IsCurrentTime)
                {
                    SelectedTime = DateTime.Now;
                }
                else
                {
                    SelectedTime = null;
                    SelectedTime = _date;
                }
            }

            _popup = GetTemplateChild(PopupTemplateName) as Popup;
            if (_popup != null)
            {
                _popup.Opened -= Popup_Opened;
                _popup.Opened += Popup_Opened;
            }
        }

        private void Popup_Opened(object sender, EventArgs e)
        {
            if (_timeSelector != null)
            {
                _timeSelector.SetTime();
            }
        }

        private void TimeSelector_SelectedTimeChanged(object sender, RoutedPropertyChangedEventArgs<DateTime?> e)
        {
            if (_textBox != null && e.NewValue != null)
            {
                _textBox.Text = e.NewValue.Value.ToString(SelectedTimeFormat);
                SelectedTime = e.NewValue;
            }
        }
    }
}

2)TimeSelector.cs代码如下:

""
""
""
"00"
"01"
"02"
...
"21"
"22"
"23"
""
""
""
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;

namespace WPFDevelopers.Controls
{
    [TemplatePart(Name = ListBoxHourTemplateName, Type = typeof(ListBox))]
    [TemplatePart(Name = ListBoxMinuteTemplateName, Type = typeof(ListBox))]
    [TemplatePart(Name = ListBoxSecondTemplateName, Type = typeof(ListBox))]
    public class TimeSelector : Control
    {
        private const string ListBoxHourTemplateName = "PART_ListBoxHour";
        private const string ListBoxMinuteTemplateName = "PART_ListBoxMinute";
        private const string ListBoxSecondTemplateName = "PART_ListBoxSecond";

        public static readonly RoutedEvent SelectedTimeChangedEvent =
            EventManager.RegisterRoutedEvent("SelectedTimeChanged", RoutingStrategy.Bubble,
                typeof(RoutedPropertyChangedEventHandler<DateTime?>), typeof(TimeSelector));

        public static readonly DependencyProperty SelectedTimeProperty =
            DependencyProperty.Register("SelectedTime", typeof(DateTime?), typeof(TimeSelector),
                new PropertyMetadata(null, OnSelectedTimeChanged));

        public static readonly DependencyProperty ItemHeightProperty =
            DependencyProperty.Register("ItemHeight", typeof(double), typeof(TimeSelector), new PropertyMetadata(0d));

        public static readonly DependencyProperty SelectorMarginProperty =
            DependencyProperty.Register("SelectorMargin", typeof(Thickness), typeof(TimeSelector),
                new PropertyMetadata(new Thickness(0)));

        private int _hour, _minute, _second;

        private ListBox _listBoxHour, _listBoxMinute, _listBoxSecond;

        static TimeSelector()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(TimeSelector),
                new FrameworkPropertyMetadata(typeof(TimeSelector)));
        }


        public DateTime? SelectedTime
        {
            get => (DateTime?)GetValue(SelectedTimeProperty);
            set => SetValue(SelectedTimeProperty, value);
        }


        public double ItemHeight
        {
            get => (double)GetValue(ItemHeightProperty);
            set => SetValue(ItemHeightProperty, value);
        }


        public Thickness SelectorMargin
        {
            get => (Thickness)GetValue(SelectorMarginProperty);
            set => SetValue(SelectorMarginProperty, value);
        }


        public event RoutedPropertyChangedEventHandler<DateTime?> SelectedTimeChanged
        {
            add => AddHandler(SelectedTimeChangedEvent, value);
            remove => RemoveHandler(SelectedTimeChangedEvent, value);
        }

        public virtual void OnSelectedTimeChanged(DateTime? oldValue, DateTime? newValue)
        {
            var args = new RoutedPropertyChangedEventArgs<DateTime?>(oldValue, newValue, SelectedTimeChangedEvent);
            RaiseEvent(args);
        }

        private static void OnSelectedTimeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var ctrl = d as TimeSelector;
            if (ctrl != null)
                ctrl.OnSelectedTimeChanged((DateTime?)e.OldValue, (DateTime?)e.NewValue);
        }


        private double GetItemHeight(ListBox listBox)
        {
            if (listBox.Items.Count > 0)
            {
                var listBoxItem = listBox.ItemContainerGenerator.ContainerFromIndex(0) as ListBoxItem;
                if (listBoxItem != null) return listBoxItem.ActualHeight;
            }

            return 0;
        }

        private int GetFirstNonEmptyItemIndex(ListBox listBox)
        {
            for (var i = 0; i < listBox.Items.Count; i++)
            {
                var item = listBox.Items[i] as string;
                if (!string.IsNullOrWhiteSpace(item))
                    return i;
            }

            return -1;
        }


        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            var minuteSecondList = Enumerable.Range(0, 60).Select(num => num.ToString("D2"));
            var emptyData = Enumerable.Repeat(string.Empty, 4);
            var result = emptyData.Concat(minuteSecondList).Concat(emptyData);
            _listBoxHour = GetTemplateChild(ListBoxHourTemplateName) as ListBox;
            if (_listBoxHour != null)
            {
                var hours = Enumerable.Range(0, 24).Select(num => num.ToString("D2"));
                _listBoxHour.SelectionChanged -= ListBoxHour_SelectionChanged;
                _listBoxHour.SelectionChanged += ListBoxHour_SelectionChanged;
                _listBoxHour.ItemsSource = emptyData.Concat(hours).Concat(emptyData);
                _listBoxHour.Loaded += (sender, args) =>
                {
                    var h = GetItemHeight(_listBoxHour);
                    if (h <= 0) return;
                    ItemHeight = h;
                    Height = h * 10;
                    var YAxis = GetFirstNonEmptyItemIndex(_listBoxHour) * h;
                    SelectorMargin = new Thickness(0, YAxis, 0, 0);
                };
            }

            _listBoxMinute = GetTemplateChild(ListBoxMinuteTemplateName) as ListBox;
            if (_listBoxMinute != null)
            {
                _listBoxMinute.SelectionChanged -= ListBoxMinute_SelectionChanged;
                _listBoxMinute.SelectionChanged += ListBoxMinute_SelectionChanged;
                _listBoxMinute.ItemsSource = result;
            }

            _listBoxSecond = GetTemplateChild(ListBoxSecondTemplateName) as ListBox;
            if (_listBoxSecond != null)
            {
                _listBoxSecond.SelectionChanged -= ListBoxSecond_SelectionChanged;
                _listBoxSecond.SelectionChanged += ListBoxSecond_SelectionChanged;
                _listBoxSecond.ItemsSource = result;
            }
        }

        private void ListBoxSecond_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (string.IsNullOrWhiteSpace(_listBoxSecond.SelectedValue.ToString())) return;
            _second = Convert.ToInt32(_listBoxSecond.SelectedValue.ToString());
            SetSelectedTime();
        }

        private void ListBoxMinute_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (string.IsNullOrWhiteSpace(_listBoxMinute.SelectedValue.ToString())) return;
            _minute = Convert.ToInt32(_listBoxMinute.SelectedValue.ToString());
            SetSelectedTime();
        }

        private void ListBoxHour_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (string.IsNullOrWhiteSpace(_listBoxHour.SelectedValue.ToString())) return;
            _hour = Convert.ToInt32(_listBoxHour.SelectedValue.ToString());
            SetSelectedTime();
        }

        private void SetSelectedTime()
        {
            var dt = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, _hour, _minute,
                _second);
            SelectedTime = dt;
        }

        public void SetTime()
        {
            if (!SelectedTime.HasValue)
                return;
            _hour = SelectedTime.Value.Hour;
            _minute = SelectedTime.Value.Minute;
            _second = SelectedTime.Value.Second;

            _listBoxHour.SelectionChanged -= ListBoxHour_SelectionChanged;
            var hour = _hour.ToString("D2");
            _listBoxHour.SelectedItem = hour;
            //(_listBoxHour as TimeSelectorListBox).Positioning();
            _listBoxHour.SelectionChanged += ListBoxHour_SelectionChanged;


            _listBoxMinute.SelectionChanged -= ListBoxMinute_SelectionChanged;
            var minute = _minute.ToString("D2");
            _listBoxMinute.SelectedItem = minute;
            //(_listBoxMinute as TimeSelectorListBox).Positioning();
            _listBoxMinute.SelectionChanged += ListBoxMinute_SelectionChanged;

            _listBoxSecond.SelectionChanged -= ListBoxSecond_SelectionChanged;
            var second = _second.ToString("D2");
            _listBoxSecond.SelectedItem = second;
            //(_listBoxSecond as TimeSelectorListBox).Positioning();
            _listBoxSecond.SelectionChanged += ListBoxSecond_SelectionChanged;

            SetSelectedTime();
        }
    }
}

3)代码TimeSelectorListBox.cs如下:

using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using WPFDevelopers.Helpers;

namespace WPFDevelopers.Controls
{
    public class TimeSelectorListBox : ListBox
    {
        private bool isFirst = true;
        private double lastIndex = 4;
        private ScrollViewer scrollViewer;

        public TimeSelectorListBox()
        {
            Loaded += TimeSelectorListBox_Loaded;
            PreviewMouseWheel -= ScrollListBox_PreviewMouseWheel;
            PreviewMouseWheel += ScrollListBox_PreviewMouseWheel;
        }
        protected override bool IsItemItsOwnContainerOverride(object item)
        {
            return item is TimeSelectorItem;
        }

        protected override DependencyObject GetContainerForItemOverride()
        {
            return new TimeSelectorItem();
        }

        private void ScrollListBox_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
        {
            if (Items != null && Items.Count > 0)
            {
                var delta = e.Delta;
                var scrollCount = delta > 0 ? -1 : 1;
                ItemPositioning(scrollCount);
                e.Handled = true;
            }
        }
        void ItemPositioning(int scrollCount)
        {
            var itemCount = Items.Count;
            var newIndex = SelectedIndex + scrollCount;
            if (newIndex < 4)
                newIndex = 5;
            else if (newIndex >= itemCount - 4)
                newIndex = itemCount;
            SelectedIndex = newIndex;
        }
        void Positioning()
        {
            if (SelectedIndex <= 0 || scrollViewer == null) return;
            var index = SelectedIndex - (int)lastIndex;
            var offset = scrollViewer.VerticalOffset + index;
            scrollViewer.ScrollToVerticalOffset(offset);
        }
        private void TimeSelectorListBox_Loaded(object sender, RoutedEventArgs e)
        {
            scrollViewer = ControlsHelper.FindVisualChild<ScrollViewer>(this);
            if (scrollViewer != null)
            {
                scrollViewer.ScrollChanged -= ScrollViewer_ScrollChanged;
                scrollViewer.ScrollChanged += ScrollViewer_ScrollChanged;
            }
        }

        private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            var offset = e.VerticalOffset;
            if (isFirst == false)
                lastIndex = offset + 4;
            else
            {
                lastIndex = offset == 0 ? 4 : offset + 4;
                isFirst = false;
            }
        }

        protected override void OnSelectionChanged(SelectionChangedEventArgs e)
        {
            base.OnSelectionChanged(e);
            if (SelectedIndex != -1 && lastIndex != -1)
            {
                if (SelectedIndex <= 0) return;
                Positioning();
            }
        }
    }
}

4)代码TimePicker.xaml如下:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:controls="clr-namespace:WPFDevelopers.Controls"
    xmlns:helpers="clr-namespace:WPFDevelopers.Helpers">

    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="Basic/ControlBasic.xaml" />
    </ResourceDictionary.MergedDictionaries>

    <ControlTemplate x:Key="WD.TimePickerToggleButton" TargetType="{x:Type ToggleButton}">
        <Border
            x:Name="PART_Border"
            Padding="6,0"
            Background="Transparent"
            BorderThickness="0"
            SnapsToDevicePixels="true">
            <controls:PathIcon
                x:Name="PART_PathIcon"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
                Foreground="{DynamicResource WD.PlaceholderTextSolidColorBrush}"
                IsHitTestVisible="False"
                Kind="Time" />
        </Border>
        <ControlTemplate.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter TargetName="PART_PathIcon" Property="Foreground" Value="{DynamicResource WD.PrimaryNormalSolidColorBrush}" />
            </Trigger>
            <Trigger Property="IsChecked" Value="True">
                <Setter TargetName="PART_PathIcon" Property="Foreground" Value="{DynamicResource WD.PrimaryNormalSolidColorBrush}" />
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>
    <Style
        x:Key="WD.TimeSelectorItem"
        BasedOn="{StaticResource WD.DefaultListBoxItem}"
        TargetType="{x:Type controls:TimeSelectorItem}">
        <Setter Property="BorderThickness" Value="0" />
        <Setter Property="HorizontalContentAlignment" Value="Center" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type controls:TimeSelectorItem}">
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter Property="FontWeight" Value="Bold" />
                            <Setter Property="Background" Value="Transparent" />
                        </Trigger>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Background" Value="{DynamicResource WD.BaseSolidColorBrush}" />
                        </Trigger>
                        <DataTrigger Binding="{Binding}" Value="">
                            <Setter Property="IsEnabled" Value="False" />
                        </DataTrigger>
                    </ControlTemplate.Triggers>
                    <controls:SmallPanel>
                        <Border
                            Name="PART_Border"
                            Padding="{TemplateBinding Padding}"
                            Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            SnapsToDevicePixels="True">
                            <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
                        </Border>
                    </controls:SmallPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <Style
        x:Key="WD.TimeListStyle"
        BasedOn="{StaticResource WD.DefaultListBox}"
        TargetType="{x:Type controls:TimeSelectorListBox}">
        <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden" />
        <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden" />
        <Setter Property="BorderThickness" Value="0" />
        <Setter Property="VirtualizingStackPanel.IsVirtualizing" Value="False" />
        <Setter Property="ItemContainerStyle" Value="{StaticResource WD.TimeSelectorItem}" />
        <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto" />
                <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
            </Trigger>
        </Style.Triggers>
    </Style>


    <Style
        x:Key="WD.TimeSelector"
        BasedOn="{StaticResource WD.ControlBasicStyle}"
        TargetType="{x:Type controls:TimeSelector}">
        <Setter Property="HorizontalContentAlignment" Value="Left" />
        <Setter Property="VerticalContentAlignment" Value="Center" />
        <Setter Property="Padding" Value="{StaticResource WD.DefaultPadding}" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type controls:TimeSelector}">
                    <Border
                        Padding="{TemplateBinding Padding}"
                        Background="{TemplateBinding Background}"
                        BorderThickness="{TemplateBinding BorderThickness}"
                        SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                        UseLayoutRounding="{TemplateBinding UseLayoutRounding}">
                        <controls:SmallPanel SnapsToDevicePixels="True">
                            <UniformGrid Rows="1">
                                <controls:TimeSelectorListBox x:Name="PART_ListBoxHour" Style="{StaticResource WD.TimeListStyle}" />
                                <controls:TimeSelectorListBox x:Name="PART_ListBoxMinute" Style="{StaticResource WD.TimeListStyle}" />
                                <controls:TimeSelectorListBox x:Name="PART_ListBoxSecond" Style="{StaticResource WD.TimeListStyle}" />
                            </UniformGrid>
                            <Line />
                            <Path />
                            <Border
                                Height="{TemplateBinding ItemHeight}"
                                Margin="{TemplateBinding SelectorMargin}"
                                VerticalAlignment="Top"
                                BorderBrush="{DynamicResource WD.BaseSolidColorBrush}"
                                BorderThickness="0,1"
                                IsHitTestVisible="False" />
                        </controls:SmallPanel>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <Style
        x:Key="WD.TimePicker"
        BasedOn="{StaticResource WD.ControlBasicStyle}"
        TargetType="{x:Type controls:TimePicker}">
        <Setter Property="HorizontalContentAlignment" Value="Left" />
        <Setter Property="VerticalContentAlignment" Value="Center" />
        <Setter Property="BorderBrush" Value="{DynamicResource WD.BaseSolidColorBrush}" />
        <Setter Property="BorderThickness" Value="1" />
        <Setter Property="Background" Value="{DynamicResource WD.BackgroundSolidColorBrush}" />
        <Setter Property="Padding" Value="{StaticResource WD.DefaultPadding}" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type controls:TimePicker}">
                    <ControlTemplate.Resources>
                        <Storyboard x:Key="OpenStoryboard">
                            <DoubleAnimation
                                EasingFunction="{StaticResource WD.ExponentialEaseOut}"
                                Storyboard.TargetName="PART_DropDown"
                                Storyboard.TargetProperty="(Grid.RenderTransform).(ScaleTransform.ScaleY)"
                                To="1"
                                Duration="00:00:.2" />
                        </Storyboard>
                        <Storyboard x:Key="CloseStoryboard">
                            <DoubleAnimation
                                EasingFunction="{StaticResource WD.ExponentialEaseOut}"
                                Storyboard.TargetName="PART_DropDown"
                                Storyboard.TargetProperty="(Grid.RenderTransform).(ScaleTransform.ScaleY)"
                                To="0"
                                Duration="00:00:.2" />
                        </Storyboard>
                    </ControlTemplate.Resources>
                    <controls:SmallPanel SnapsToDevicePixels="True">
                        <Grid Background="Transparent">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition />
                                <ColumnDefinition Width="Auto" />
                            </Grid.ColumnDefinitions>
                            <Border
                                Name="PART_Border"
                                Grid.ColumnSpan="2"
                                Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}"
                                CornerRadius="{Binding Path=(helpers:ElementHelper.CornerRadius), RelativeSource={RelativeSource TemplatedParent}}"
                                SnapsToDevicePixels="True" />
                            <TextBox
                                x:Name="PART_EditableTextBox"
                                Margin="{TemplateBinding Padding}"
                                HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                Background="{TemplateBinding Background}"
                                Focusable="True"
                                Foreground="{DynamicResource WD.PrimaryTextSolidColorBrush}"
                                SelectionBrush="{DynamicResource WD.WindowBorderBrushSolidColorBrush}"
                                Style="{x:Null}"
                                Template="{StaticResource WD.ComboBoxTextBox}" />
                            <TextBlock
                                x:Name="PART_Watermark"
                                Margin="{TemplateBinding Padding}"
                                Padding="1,0"
                                HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                Background="Transparent"
                                FontSize="{StaticResource WD.NormalFontSize}"
                                Foreground="{DynamicResource WD.RegularTextSolidColorBrush}"
                                IsHitTestVisible="False"
                                Text="{Binding Path=(helpers:ElementHelper.Watermark), RelativeSource={RelativeSource TemplatedParent}}"
                                TextTrimming="CharacterEllipsis"
                                Visibility="Collapsed" />
                            <ToggleButton
                                x:Name="PART_ToggleButton"
                                Grid.Column="1"
                                Background="{TemplateBinding Background}"
                                ClickMode="Release"
                                Focusable="False"
                                Style="{x:Null}"
                                Template="{StaticResource WD.TimePickerToggleButton}" />
                            <Popup
                                x:Name="PART_Popup"
                                AllowsTransparency="True"
                                IsOpen="{Binding Path=IsChecked, ElementName=PART_ToggleButton}"
                                Placement="Bottom"
                                PlacementTarget="{Binding ElementName=PART_Border}"
                                StaysOpen="False">
                                <controls:SmallPanel
                                    x:Name="PART_DropDown"
                                    MinWidth="{TemplateBinding FrameworkElement.ActualWidth}"
                                    MaxHeight="{TemplateBinding MaxDropDownHeight}"
                                    Margin="24,2,24,24"
                                    RenderTransformOrigin=".5,0"
                                    SnapsToDevicePixels="True">
                                    <controls:SmallPanel.RenderTransform>
                                        <ScaleTransform ScaleY="0" />
                                    </controls:SmallPanel.RenderTransform>
                                    <Border
                                        Name="PART_DropDownBorder"
                                        Background="{TemplateBinding Background}"
                                        BorderBrush="{TemplateBinding BorderBrush}"
                                        BorderThickness="{TemplateBinding BorderThickness}"
                                        CornerRadius="{Binding Path=(helpers:ElementHelper.CornerRadius), RelativeSource={RelativeSource TemplatedParent}}"
                                        Effect="{StaticResource WD.PopupShadowDepth}"
                                        SnapsToDevicePixels="True"
                                        UseLayoutRounding="True" />
                                    <controls:TimeSelector x:Name="PART_TimeSelector" />
                                </controls:SmallPanel>
                            </Popup>
                        </Grid>
                    </controls:SmallPanel>
                    <ControlTemplate.Triggers>
                        <Trigger SourceName="PART_ToggleButton" Property="IsChecked" Value="True">
                            <Trigger.EnterActions>
                                <BeginStoryboard x:Name="BeginStoryboardOpenStoryboard" Storyboard="{StaticResource OpenStoryboard}" />
                            </Trigger.EnterActions>
                            <Trigger.ExitActions>
                                <StopStoryboard BeginStoryboardName="BeginStoryboardOpenStoryboard" />
                            </Trigger.ExitActions>
                        </Trigger>
                        <Trigger SourceName="PART_ToggleButton" Property="IsChecked" Value="False">
                            <Trigger.EnterActions>
                                <BeginStoryboard x:Name="BeginStoryboardCloseStoryboard" Storyboard="{StaticResource CloseStoryboard}" />
                            </Trigger.EnterActions>
                            <Trigger.ExitActions>
                                <StopStoryboard BeginStoryboardName="BeginStoryboardCloseStoryboard" />
                            </Trigger.ExitActions>
                        </Trigger>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="PART_Border" Property="BorderBrush" Value="{DynamicResource WD.PrimaryNormalSolidColorBrush}" />
                        </Trigger>
                        <Trigger SourceName="PART_Popup" Property="AllowsTransparency" Value="True">
                            <Setter TargetName="PART_DropDownBorder" Property="Margin" Value="0,2,0,0" />
                        </Trigger>
                        <Trigger Property="SelectedTime" Value="">
                            <Setter TargetName="PART_Watermark" Property="Visibility" Value="Visible" />
                        </Trigger>
                        <Trigger Property="SelectedTime" Value="{x:Null}">
                            <Setter TargetName="PART_Watermark" Property="Visibility" Value="Visible" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <Style BasedOn="{StaticResource WD.TimeSelector}" TargetType="{x:Type controls:TimeSelector}" />
    <Style BasedOn="{StaticResource WD.TimePicker}" TargetType="{x:Type controls:TimePicker}" />

</ResourceDictionary>

5)示例代码TimePickerExample.xaml如下:

<UniformGrid>
            <wd:TimePicker
                Width="200"
                VerticalAlignment="Center"
                wd:ElementHelper.Watermark="请选择任意时间" />
            <wd:TimePicker
                Width="200"
                VerticalAlignment="Center"
                IsCurrentTime="True" />
            <wd:TimePicker
                Width="200"
                VerticalAlignment="Center"
                SelectedTime="2023-05-06 23:59:59" />
</UniformGrid>

效果图

以上就是基于WPF实现时间选择控件的详细内容,更多关于WPF时间选择控件的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文