欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于WPF實(shí)現(xiàn)時(shí)間選擇控件

 更新時(shí)間:2023年12月20日 10:21:18   作者:WPF開發(fā)者  
這篇文章主要介紹了如何基于WPF實(shí)現(xiàn)簡單的時(shí)間選擇控件,文中的示例代碼講解詳細(xì),對(duì)我們的學(xué)習(xí)或工作有一定幫助,需要的小伙伴可以參考一下

WPF 實(shí)現(xiàn)時(shí)間選擇控件

  • 框架使用.NET4 至 .NET6;
  • Visual Studio 2022;

實(shí)現(xiàn)代碼

1)代碼TimePicker.cs如下:

  • TimePicker控件依賴屬性,SelectedTimeFormatProperty、MaxDropDownHeightProperty、SelectedTimePropertyIsCurrentTimeProperty。
  • 在靜態(tài)構(gòu)造函數(shù)中,使用DefaultStyleKeyProperty.OverrideMetadata方法來指定控件的默認(rèn)樣式。
  • 控件的模板部分定義了三個(gè)重要的部件:PART_TimeSelector(列表框用于選擇時(shí)間)、PART_EditableTextBox(可編輯的文本框)和PART_Popup(彈出窗口)。
  • 在應(yīng)用模板時(shí),我們獲取并保存了這些模板部件的引用。并且訂閱了時(shí)間選擇器的SelectedTimeChanged事件,以及彈出窗口的Opened事件。
  • 當(dāng)時(shí)間選擇器的SelectedTimeChanged事件發(fā)生時(shí),我們會(huì)更新文本框中的文本,并將選中的時(shí)間賦值給SelectedTime屬性。
  • 當(dāng)彈出窗口的Opened事件發(fā)生時(shí),我們會(huì)調(diào)用時(shí)間選擇器的SetTime方法,以根據(jù)SelectedTime的值更新列表框的選擇項(xiàng)。
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代碼如下:

  • 三個(gè)列表框,分別用于選擇小時(shí)、分鐘和秒。
  • 代碼中定義了一些依賴屬性,例如SelectedTimeProperty用于獲取或設(shè)置選中的時(shí)間,ItemHeightProperty用于設(shè)置列表項(xiàng)的高度,SelectorMarginProperty用于設(shè)置選擇器的邊距。還定義了一個(gè)SelectedTimeChangedEvent事件,用于在選中時(shí)間發(fā)生變化時(shí)觸發(fā)。
  • 控件的模板部分包含了三個(gè)列表框,分別命名為PART_ListBoxHour、PART_ListBoxMinutePART_ListBoxSecond。在應(yīng)用模板時(shí),會(huì)將數(shù)據(jù)源綁定到列表框上,并為每個(gè)列表框添加SelectionChanged事件的處理程序。
  • 在列表框的SelectionChanged事件處理程序中,會(huì)根據(jù)選擇的項(xiàng)更新_hour、_minute_second等字段,并通過SetSelectedTime方法設(shè)置SelectedTime屬性的值。
  • 最后在SetTime方法中會(huì)根據(jù)SelectedTime的值來更新列表框的選擇項(xiàng),并調(diào)用SetSelectedTime方法設(shè)置SelectedTime屬性的值。
  • 小時(shí)集合設(shè)置為 _listBoxHour 的 ItemsSource。這個(gè)集合由上下四個(gè)空字符串、從0到23的小時(shí)數(shù)(格式為兩位數(shù))。
""
""
""
"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如下:

  • TimeSelectorListBox 是一個(gè)自定義的 ListBox 控件,繼承自 ListBox 類。
  • scrollViewer 是一個(gè) ScrollViewer 對(duì)象,用于滾動(dòng) ListBox 中的項(xiàng)。
  • lastIndex 用于存儲(chǔ)上次滾動(dòng)時(shí) ListBox 中選中項(xiàng)的索引位置。
  • isFirst 用于判斷是否為第一次滾動(dòng)。
  • IsItemItsOwnContainerOverride 方法重寫了 ListBox 的方法,用于指定 ListBox 的項(xiàng)是否為指定的容器類型(TimeSelectorItem)。
  • GetContainerForItemOverride 方法重寫了 ListBox 的方法,用于創(chuàng)建 ListBox 的項(xiàng)所使用的容器(TimeSelectorItem)。
  • 構(gòu)造函數(shù) TimeSelectorListBox 對(duì)控件進(jìn)行初始化,設(shè)置 Loaded 和 PreviewMouseWheel 事件的處理一次滾動(dòng)一條內(nèi)容。
  • TimeSelectorListBox_Loaded 方法用于在控件加載完成后執(zhí)行一些初始化操作,如獲取 ScrollViewer 對(duì)象并監(jiān)聽其 ScrollChanged 事件。
  • ScrollListBox_PreviewMouseWheel 方法在鼠標(biāo)滾輪滾動(dòng)時(shí)處理滾動(dòng)邏輯,根據(jù)滾動(dòng)方向和選擇項(xiàng)的位置來調(diào)整 ListBox 的選中項(xiàng),并防止?jié)L動(dòng)穿透。
  • ScrollViewer_ScrollChanged 方法在 ScrollViewer 的滾動(dòng)位置發(fā)生變化時(shí)更新 lastIndex 的值。
  • OnSelectionChanged 方法重寫了 ListBox 的方法,在選中項(xiàng)發(fā)生改變時(shí)執(zhí)行自定義操作,通過計(jì)算選中項(xiàng)與上次滾動(dòng)位置之間的索引差來調(diào)整 ScrollViewer 的滾動(dòng)位置。
  • FindVisualChild 方法用遞歸的方式在 Visual 樹中查找指定類型的子元素,并返回找到的第一個(gè)匹配項(xiàng)。
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="請(qǐng)選擇任意時(shí)間" />
            <wd:TimePicker
                Width="200"
                VerticalAlignment="Center"
                IsCurrentTime="True" />
            <wd:TimePicker
                Width="200"
                VerticalAlignment="Center"
                SelectedTime="2023-05-06 23:59:59" />
</UniformGrid>

效果圖

以上就是基于WPF實(shí)現(xiàn)時(shí)間選擇控件的詳細(xì)內(nèi)容,更多關(guān)于WPF時(shí)間選擇控件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C#中的委托介紹

    C#中的委托介紹

    這篇文章主要介紹了C#中的委托介紹,本文講解了聲明委托的方式、匿名方法、多播委托等內(nèi)容,需要的朋友可以參考下
    2015-01-01
  • C#創(chuàng)建一個(gè)可快速重復(fù)使用的項(xiàng)目模板(詳細(xì)過程)

    C#創(chuàng)建一個(gè)可快速重復(fù)使用的項(xiàng)目模板(詳細(xì)過程)

    這篇文章主要介紹了C#如何創(chuàng)建一個(gè)可快速重復(fù)使用的項(xiàng)目模板今天給大家介紹的是基于官方的cli donet new 命令創(chuàng)建自己的項(xiàng)目模板,需要的朋友可以參考下
    2024-06-06
  • C#的并發(fā)機(jī)制優(yōu)秀在哪你知道么

    C#的并發(fā)機(jī)制優(yōu)秀在哪你知道么

    這篇文章主要為大家詳細(xì)介紹了C#的并發(fā)機(jī)制,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • C#多線程之任務(wù)的用法詳解

    C#多線程之任務(wù)的用法詳解

    本文詳細(xì)講解了C#多線程之任務(wù)的用法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-04-04
  • C#使用Socket發(fā)送和接收TCP數(shù)據(jù)實(shí)例

    C#使用Socket發(fā)送和接收TCP數(shù)據(jù)實(shí)例

    這篇文章主要介紹了C#使用Socket發(fā)送和接收TCP數(shù)據(jù)的實(shí)現(xiàn)方法,以實(shí)例的形式詳細(xì)講述了C#實(shí)現(xiàn)socket通信的完整實(shí)現(xiàn)過程,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2014-10-10
  • C# JsonHelper 操作輔助類,拿來直接用

    C# JsonHelper 操作輔助類,拿來直接用

    本文總結(jié)了一些常用的JSON操作輔助類,包括轉(zhuǎn)換、判斷、Ajax異步等操作,希望能幫到大家。
    2016-05-05
  • 客戶端實(shí)現(xiàn)藍(lán)牙接收(C#)知識(shí)總結(jié)

    客戶端實(shí)現(xiàn)藍(lán)牙接收(C#)知識(shí)總結(jié)

    網(wǎng)上有關(guān)藍(lán)牙接收的資料很多,使用起來也很簡單,但是我覺得還是有必要把這些知識(shí)總結(jié)下來,藍(lán)牙開發(fā)需要用到一個(gè)第三方的庫InTheHand.Net.Personal.dll,感興趣的朋友可以了解下,或許對(duì)你有所幫助
    2013-02-02
  • C#操作注冊(cè)表的方法

    C#操作注冊(cè)表的方法

    以下從‘讀’‘寫’‘刪除’‘判斷’四個(gè)事例實(shí)現(xiàn)對(duì)注冊(cè)表的簡單操作
    2007-03-03
  • C# Dynamic之:ExpandoObject,DynamicObject,DynamicMetaOb的應(yīng)用(上)

    C# Dynamic之:ExpandoObject,DynamicObject,DynamicMetaOb的應(yīng)用(上)

    本篇文章對(duì)C#中ExpandoObject,DynamicObject,DynamicMetaOb的應(yīng)用進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • 利用C#實(shí)現(xiàn)將小數(shù)值四舍五入為整數(shù)

    利用C#實(shí)現(xiàn)將小數(shù)值四舍五入為整數(shù)

    在項(xiàng)目的開發(fā)中,遇到一些除法計(jì)算內(nèi)容會(huì)產(chǎn)生小數(shù)值,但是又需要根據(jù)項(xiàng)目的實(shí)際情況將這些小數(shù)內(nèi)容化為整數(shù),所以本文為大家整理了C#實(shí)現(xiàn)將小數(shù)值四舍五入為整數(shù)的方法,希望對(duì)大家有所幫助
    2023-07-07

最新評(píng)論