From ed8ef8c7a9dbbaf519dd343fb3a4161b4d23145d Mon Sep 17 00:00:00 2001 From: NaBian <836904362@qq.com> Date: Tue, 20 Nov 2018 15:31:10 +0800 Subject: [PATCH] add datetimepicker --- .../Attach/BackgroundSwitchElement.cs | 1 - HandyControl/Controls/Attach/BorderElement.cs | 1 - .../Controls/Attach/DataGridAttach.cs | 1 - HandyControl/Controls/Attach/TitleElement.cs | 17 + HandyControl/Controls/Input/DateTimePicker.cs | 690 ++++++++++++++++++ HandyControl/Controls/Input/TimePicker.cs | 61 +- .../Controls/Time/CalendarWithClock.cs | 260 +++++++ .../Controls/{ => Time}/Clock/Clock.cs | 82 ++- .../{ => Time}/Clock/ClockRadioButton.cs | 0 .../{ => Time}/TimeBar/SpeTextBlock.cs | 0 .../Controls/{ => Time}/TimeBar/TimeBar.cs | 0 HandyControl/HandyControl.csproj | 23 +- .../Styles/Base/DateTimePickerBaseStyle.xaml | 338 +++++++++ .../Styles/Base/TimePickerBaseStyle.xaml | 20 +- HandyControl/Themes/Styles/Calendar.xaml | 7 +- .../Themes/Styles/CalendarWithClock.xaml | 44 ++ HandyControl/Themes/Styles/Clock.xaml | 9 +- .../Themes/Styles/DateTimePicker.xaml | 15 + HandyControl/Themes/Styles/Style.xaml | 2 + HandyControlDemo/Data/MessageToken.cs | 4 + HandyControlDemo/Data/MessageToken.tt | 4 +- HandyControlDemo/HandyControlDemo.csproj | 14 + .../Properties/Langs/Lang.Designer.cs | 20 +- .../Properties/Langs/Lang.en.resx | 6 + HandyControlDemo/Properties/Langs/Lang.resx | 6 + .../Controls/CalendarWithClockDemoCtl.xaml | 9 + .../Controls/CalendarWithClockDemoCtl.xaml.cs | 10 + .../Controls/DatePickerDemoCtl.xaml | 2 +- .../Controls/DateTimePickerDemoCtl.xaml | 31 + .../Controls/DateTimePickerDemoCtl.xaml.cs | 10 + .../Controls/TimePickerDemoCtl.xaml.cs | 6 +- .../UserControl/Main/LeftMainContent.xaml | 24 +- 32 files changed, 1611 insertions(+), 106 deletions(-) create mode 100644 HandyControl/Controls/Attach/TitleElement.cs create mode 100644 HandyControl/Controls/Input/DateTimePicker.cs create mode 100644 HandyControl/Controls/Time/CalendarWithClock.cs rename HandyControl/Controls/{ => Time}/Clock/Clock.cs (85%) rename HandyControl/Controls/{ => Time}/Clock/ClockRadioButton.cs (100%) rename HandyControl/Controls/{ => Time}/TimeBar/SpeTextBlock.cs (100%) rename HandyControl/Controls/{ => Time}/TimeBar/TimeBar.cs (100%) create mode 100644 HandyControl/Themes/Styles/Base/DateTimePickerBaseStyle.xaml create mode 100644 HandyControl/Themes/Styles/CalendarWithClock.xaml create mode 100644 HandyControl/Themes/Styles/DateTimePicker.xaml create mode 100644 HandyControlDemo/UserControl/Controls/CalendarWithClockDemoCtl.xaml create mode 100644 HandyControlDemo/UserControl/Controls/CalendarWithClockDemoCtl.xaml.cs create mode 100644 HandyControlDemo/UserControl/Controls/DateTimePickerDemoCtl.xaml create mode 100644 HandyControlDemo/UserControl/Controls/DateTimePickerDemoCtl.xaml.cs diff --git a/HandyControl/Controls/Attach/BackgroundSwitchElement.cs b/HandyControl/Controls/Attach/BackgroundSwitchElement.cs index 09da3666..c690435b 100644 --- a/HandyControl/Controls/Attach/BackgroundSwitchElement.cs +++ b/HandyControl/Controls/Attach/BackgroundSwitchElement.cs @@ -1,7 +1,6 @@ using System.Windows; using System.Windows.Media; -// ReSharper disable once CheckNamespace namespace HandyControl.Controls { public class BackgroundSwitchElement : DependencyObject diff --git a/HandyControl/Controls/Attach/BorderElement.cs b/HandyControl/Controls/Attach/BorderElement.cs index 8868c3c2..451095e1 100644 --- a/HandyControl/Controls/Attach/BorderElement.cs +++ b/HandyControl/Controls/Attach/BorderElement.cs @@ -1,6 +1,5 @@ using System.Windows; -// ReSharper disable once CheckNamespace namespace HandyControl.Controls { public class BorderElement : DependencyObject diff --git a/HandyControl/Controls/Attach/DataGridAttach.cs b/HandyControl/Controls/Attach/DataGridAttach.cs index 3385ac3d..f122cab3 100644 --- a/HandyControl/Controls/Attach/DataGridAttach.cs +++ b/HandyControl/Controls/Attach/DataGridAttach.cs @@ -2,7 +2,6 @@ using System.Windows; using System.Windows.Controls; -// ReSharper disable once CheckNamespace namespace HandyControl.Controls { public class DataGridAttach : DependencyObject diff --git a/HandyControl/Controls/Attach/TitleElement.cs b/HandyControl/Controls/Attach/TitleElement.cs new file mode 100644 index 00000000..c5a1a711 --- /dev/null +++ b/HandyControl/Controls/Attach/TitleElement.cs @@ -0,0 +1,17 @@ +using System.Windows; +using System.Windows.Media; + +namespace HandyControl.Controls +{ + public class TitleElement : DependencyObject + { + public static readonly DependencyProperty BackgroundProperty = DependencyProperty.RegisterAttached( + "Background", typeof(Brush), typeof(TitleElement), new FrameworkPropertyMetadata(default(Brush), FrameworkPropertyMetadataOptions.Inherits)); + + public static void SetBackground(DependencyObject element, Brush value) + => element.SetValue(BackgroundProperty, value); + + public static Brush GetBackground(DependencyObject element) + => (Brush) element.GetValue(BackgroundProperty); + } +} \ No newline at end of file diff --git a/HandyControl/Controls/Input/DateTimePicker.cs b/HandyControl/Controls/Input/DateTimePicker.cs new file mode 100644 index 00000000..c32c83ec --- /dev/null +++ b/HandyControl/Controls/Input/DateTimePicker.cs @@ -0,0 +1,690 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Input; +using System.Windows.Threading; +using HandyControl.Data; +using HandyControl.Interactivity; + +namespace HandyControl.Controls +{ + /// + /// 时间日期选择器 + /// + [TemplatePart(Name = ElementRoot, Type = typeof(Grid))] + [TemplatePart(Name = ElementTextBox, Type = typeof(WatermarkTextBox))] + [TemplatePart(Name = ElementButton, Type = typeof(Button))] + [TemplatePart(Name = ElementPopup, Type = typeof(Popup))] + public class DateTimePicker : Control, IDataInput + { + #region Constants + + private const string ElementRoot = "PART_Root"; + + private const string ElementTextBox = "PART_TextBox"; + + private const string ElementButton = "PART_Button"; + + private const string ElementPopup = "PART_Popup"; + + #endregion Constants + + #region Data + + private CalendarWithClock _calendarWithClock; + + private string _defaultText; + + private ButtonBase _dropDownButton; + + private Popup _popUp; + + private bool _disablePopupReopen; + + private WatermarkTextBox _textBox; + + private IDictionary _isHandlerSuspended; + + private DateTime? _originalSelectedDateTime; + + #endregion Data + + #region Public Events + + public static readonly RoutedEvent SelectedDateTimeChangedEvent = + EventManager.RegisterRoutedEvent("SelectedDateTimeChanged", RoutingStrategy.Direct, + typeof(EventHandler>), typeof(DateTimePicker)); + + public event EventHandler> SelectedDateTimeChanged + { + add => AddHandler(SelectedDateTimeChangedEvent, value); + remove => RemoveHandler(SelectedDateTimeChangedEvent, value); + } + + public event RoutedEventHandler PickerClosed; + + public event RoutedEventHandler PickerOpened; + + #endregion Public Events + + static DateTimePicker() + { + EventManager.RegisterClassHandler(typeof(DateTimePicker), GotFocusEvent, new RoutedEventHandler(OnGotFocus)); + KeyboardNavigation.TabNavigationProperty.OverrideMetadata(typeof(DateTimePicker), new FrameworkPropertyMetadata(KeyboardNavigationMode.Once)); + KeyboardNavigation.IsTabStopProperty.OverrideMetadata(typeof(DateTimePicker), new FrameworkPropertyMetadata(false)); + } + + public DateTimePicker() + { + InitCalendarWithClock(); + CommandBindings.Add(new CommandBinding(ControlCommands.Clear, (s, e) => + { + ClearValue(SelectedDateTimeProperty); + ClearValue(TextProperty); + _textBox.Text = string.Empty; + })); + } + + #region Public Properties + + public static readonly DependencyProperty DateTimeFormatProperty = DependencyProperty.Register( + "DateTimeFormat", typeof(string), typeof(DateTimePicker), new PropertyMetadata("yyyy-MM-dd HH:mm:ss")); + + public string DateTimeFormat + { + get => (string) GetValue(DateTimeFormatProperty); + set => SetValue(DateTimeFormatProperty, value); + } + + public static readonly DependencyProperty ClockStyleProperty = DependencyProperty.Register( + "ClockStyle", typeof(Style), typeof(DateTimePicker), new PropertyMetadata(default(Style))); + + public Style ClockStyle + { + get => (Style) GetValue(ClockStyleProperty); + set => SetValue(ClockStyleProperty, value); + } + + public static readonly DependencyProperty CalendarStyleProperty = DependencyProperty.Register( + "CalendarStyle", typeof(Style), typeof(DateTimePicker), new PropertyMetadata(default(Style))); + + public Style CalendarStyle + { + get => (Style) GetValue(CalendarStyleProperty); + set => SetValue(CalendarStyleProperty, value); + } + + public static readonly DependencyProperty DisplayDateTimeProperty = DependencyProperty.Register( + "DisplayDateTime", typeof(DateTime), typeof(DateTimePicker), new FrameworkPropertyMetadata(DateTime.Now, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, null, CoerceDisplayDateTime)); + + private static object CoerceDisplayDateTime(DependencyObject d, object value) + { + var dp = (DateTimePicker)d; + dp._calendarWithClock.DisplayDateTime = (DateTime)value; + + return dp._calendarWithClock.DisplayDateTime; + } + + public DateTime DisplayDateTime + { + get => (DateTime) GetValue(DisplayDateTimeProperty); + set => SetValue(DisplayDateTimeProperty, value); + } + + public static readonly DependencyProperty IsDropDownOpenProperty = DependencyProperty.Register( + "IsDropDownOpen", typeof(bool), typeof(DateTimePicker), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnIsDropDownOpenChanged, OnCoerceIsDropDownOpen)); + + private static object OnCoerceIsDropDownOpen(DependencyObject d, object baseValue) => d is DateTimePicker dp && !dp.IsEnabled ? false : baseValue; + + private static void OnIsDropDownOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var dp = d as DateTimePicker; + + var newValue = (bool)e.NewValue; + if (dp?._popUp != null && dp._popUp.IsOpen != newValue) + { + dp._popUp.IsOpen = newValue; + if (newValue) + { + dp._originalSelectedDateTime = dp.SelectedDateTime; + + dp.Dispatcher.BeginInvoke(DispatcherPriority.Input, (Action)delegate + { + dp._calendarWithClock.Focus(); + }); + } + + } + } + + public bool IsDropDownOpen + { + get => (bool) GetValue(IsDropDownOpenProperty); + set => SetValue(IsDropDownOpenProperty, value); + } + + public static readonly DependencyProperty SelectedDateTimeProperty = DependencyProperty.Register( + "SelectedDateTime", typeof(DateTime?), typeof(DateTimePicker), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnSelectedDateTimeChanged, CoerceSelectedDateTime)); + + private static object CoerceSelectedDateTime(DependencyObject d, object value) + { + var dp = (DateTimePicker)d; + dp._calendarWithClock.SelectedDateTime = (DateTime?)value; + return dp._calendarWithClock.SelectedDateTime; + } + + private static void OnSelectedDateTimeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + if (!(d is DateTimePicker dp)) return; + + if (dp.SelectedDateTime.HasValue) + { + var time = dp.SelectedDateTime.Value; + dp.SetTextInternal(dp.DateTimeToString(time)); + } + + dp.RaiseEvent(new FunctionEventArgs(SelectedDateTimeChangedEvent, dp) + { + Info = dp.SelectedDateTime + }); + } + + public DateTime? SelectedDateTime + { + get => (DateTime?) GetValue(SelectedDateTimeProperty); + set => SetValue(SelectedDateTimeProperty, value); + } + + public static readonly DependencyProperty TextProperty = DependencyProperty.Register( + "Text", typeof(string), typeof(DateTimePicker), new FrameworkPropertyMetadata(string.Empty, OnTextChanged)); + + private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + if (d is DateTimePicker dp && !dp.IsHandlerSuspended(TextProperty)) + { + if (e.NewValue is string newValue) + { + if (dp._textBox != null) + { + dp._textBox.Text = newValue; + } + else + { + dp._defaultText = newValue; + } + + dp.SetSelectedDateTime(); + } + else + { + dp.SetValueNoCallback(SelectedDateTimeProperty, null); + } + } + } + + public string Text + { + get => (string) GetValue(TextProperty); + set => SetValue(TextProperty, value); + } + + /// + /// Sets the local Text property without breaking bindings + /// + /// + private void SetTextInternal(string value) + { + SetCurrentValue(TextProperty, value); + } + + public Func> VerifyFunc { get; set; } + + public static readonly DependencyProperty IsErrorProperty = DependencyProperty.Register( + "IsError", typeof(bool), typeof(DateTimePicker), new PropertyMetadata(ValueBoxes.FalseBox)); + + public bool IsError + { + get => (bool) GetValue(IsErrorProperty); + set => SetValue(IsErrorProperty, value); + } + + public static readonly DependencyProperty ErrorStrProperty = DependencyProperty.Register( + "ErrorStr", typeof(string), typeof(DateTimePicker), new PropertyMetadata(default(string))); + + public string ErrorStr + { + get => (string) GetValue(ErrorStrProperty); + set => SetValue(ErrorStrProperty, value); + } + + public static readonly DependencyProperty TextTypeProperty = DependencyProperty.Register( + "TextType", typeof(TextType), typeof(DateTimePicker), new PropertyMetadata(default(TextType))); + + public TextType TextType + { + get => (TextType) GetValue(TextTypeProperty); + set => SetValue(TextTypeProperty, value); + } + + public static readonly DependencyProperty ShowClearButtonProperty = DependencyProperty.Register( + "ShowClearButton", typeof(bool), typeof(DateTimePicker), new PropertyMetadata(ValueBoxes.FalseBox)); + + public bool ShowClearButton + { + get => (bool) GetValue(ShowClearButtonProperty); + set => SetValue(ShowClearButtonProperty, value); + } + + #endregion + + #region Public Methods + + public override void OnApplyTemplate() + { + if (DesignerProperties.GetIsInDesignMode(this)) return; + if (_popUp != null) + { + _popUp.PreviewMouseLeftButtonDown -= PopUp_PreviewMouseLeftButtonDown; + _popUp.Opened -= PopUp_Opened; + _popUp.Closed -= PopUp_Closed; + _popUp.Child = null; + } + + if (_dropDownButton != null) + { + _dropDownButton.Click -= DropDownButton_Click; + _dropDownButton.MouseLeave -= DropDownButton_MouseLeave; + } + + if (_textBox != null) + { + _textBox.KeyDown -= TextBox_KeyDown; + _textBox.TextChanged -= TextBox_TextChanged; + _textBox.LostFocus -= TextBox_LostFocus; + } + + base.OnApplyTemplate(); + + _popUp = GetTemplateChild(ElementPopup) as Popup; + _dropDownButton = GetTemplateChild(ElementButton) as Button; + _textBox = GetTemplateChild(ElementTextBox) as WatermarkTextBox; + + CheckNull(); + + _popUp.PreviewMouseLeftButtonDown += PopUp_PreviewMouseLeftButtonDown; + _popUp.Opened += PopUp_Opened; + _popUp.Closed += PopUp_Closed; + _popUp.Child = _calendarWithClock; + + if (IsDropDownOpen) + { + _popUp.IsOpen = true; + } + + _dropDownButton.Click += DropDownButton_Click; + _dropDownButton.MouseLeave += DropDownButton_MouseLeave; + if (SelectedDateTime == null) + { + _textBox.Text = DateTime.Now.ToString(DateTimeFormat); + } + _textBox.KeyDown += TextBox_KeyDown; + _textBox.TextChanged += TextBox_TextChanged; + _textBox.LostFocus += TextBox_LostFocus; + + if (SelectedDateTime == null) + { + if (!string.IsNullOrEmpty(_defaultText)) + { + _textBox.Text = _defaultText; + SetSelectedDateTime(); + } + } + else + { + _textBox.Text = DateTimeToString(SelectedDateTime.Value); + } + + if (_originalSelectedDateTime == null) + { + _originalSelectedDateTime = DateTime.Now; + } + SetCurrentValue(DisplayDateTimeProperty, _originalSelectedDateTime); + } + + public virtual bool VerifyData() + { + OperationResult result; + + if (VerifyFunc != null) + { + result = VerifyFunc.Invoke(Text); + } + else + { + if (!string.IsNullOrEmpty(Text)) + { + result = OperationResult.Success(); + } + else if (InfoElement.GetNecessary(this)) + { + result = OperationResult.Failed(Properties.Langs.Lang.IsNecessary); + } + else + { + result = OperationResult.Success(); + } + } + + IsError = !result.Data; + ErrorStr = result.Message; + return result.Data; + } + + public override string ToString() => SelectedDateTime?.ToString(DateTimeFormat) ?? string.Empty; + + #endregion + + #region Protected Methods + + protected virtual void OnPickerClosed(RoutedEventArgs e) + { + var handler = PickerClosed; + handler?.Invoke(this, e); + } + + protected virtual void OnPickerOpened(RoutedEventArgs e) + { + var handler = PickerOpened; + handler?.Invoke(this, e); + } + + #endregion Protected Methods + + #region Private Methods + + private void CheckNull() + { + if (_dropDownButton == null || _popUp == null || _textBox == null) + throw new Exception(); + } + + private void InitCalendarWithClock() + { + _calendarWithClock = new CalendarWithClock + { + ShowConfirmButton = true + }; + _calendarWithClock.SelectedDateTimeChanged += CalendarWithClock_SelectedDateTimeChanged; + _calendarWithClock.Confirmed += CalendarWithClock_Confirmed; + } + + private void CalendarWithClock_Confirmed() => TogglePopUp(); + + private void CalendarWithClock_SelectedDateTimeChanged(object sender, FunctionEventArgs e) => SelectedDateTime = e.Info; + + private void TextBox_LostFocus(object sender, RoutedEventArgs e) + { + SetSelectedDateTime(); + } + + private void SetIsHandlerSuspended(DependencyProperty property, bool value) + { + if (value) + { + if (_isHandlerSuspended == null) + { + _isHandlerSuspended = new Dictionary(2); + } + + _isHandlerSuspended[property] = true; + } + else + { + _isHandlerSuspended?.Remove(property); + } + } + + private void SetValueNoCallback(DependencyProperty property, object value) + { + SetIsHandlerSuspended(property, true); + try + { + SetCurrentValue(property, value); + } + finally + { + SetIsHandlerSuspended(property, false); + } + } + + private void TextBox_TextChanged(object sender, TextChangedEventArgs e) + { + SetValueNoCallback(TextProperty, _textBox.Text); + VerifyData(); + } + + private bool ProcessDateTimePickerKey(KeyEventArgs e) + { + switch (e.Key) + { + case Key.System: + { + switch (e.SystemKey) + { + case Key.Down: + { + if ((Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt) + { + TogglePopUp(); + return true; + } + + break; + } + } + + break; + } + + case Key.Enter: + { + SetSelectedDateTime(); + return true; + } + } + + return false; + } + + private void TextBox_KeyDown(object sender, KeyEventArgs e) + { + e.Handled = ProcessDateTimePickerKey(e) || e.Handled; + } + + private void DropDownButton_MouseLeave(object sender, MouseEventArgs e) + { + _disablePopupReopen = false; + } + + private bool IsHandlerSuspended(DependencyProperty property) + { + return _isHandlerSuspended != null && _isHandlerSuspended.ContainsKey(property); + } + + private void PopUp_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) + { + if (sender is Popup popup && !popup.StaysOpen) + { + if (_dropDownButton?.InputHitTest(e.GetPosition(_dropDownButton)) != null) + { + _disablePopupReopen = true; + } + } + } + + private void PopUp_Opened(object sender, EventArgs e) + { + if (!IsDropDownOpen) + { + SetCurrentValue(IsDropDownOpenProperty, ValueBoxes.TrueBox); + } + + _calendarWithClock?.MoveFocus(new TraversalRequest(FocusNavigationDirection.First)); + + OnPickerOpened(new RoutedEventArgs()); + } + + private void PopUp_Closed(object sender, EventArgs e) + { + if (IsDropDownOpen) + { + SetCurrentValue(IsDropDownOpenProperty, ValueBoxes.FalseBox); + } + + if (_calendarWithClock.IsKeyboardFocusWithin) + { + MoveFocus(new TraversalRequest(FocusNavigationDirection.First)); + } + + OnPickerClosed(new RoutedEventArgs()); + } + + private void DropDownButton_Click(object sender, RoutedEventArgs e) => TogglePopUp(); + + private void TogglePopUp() + { + if (IsDropDownOpen) + { + SetCurrentValue(IsDropDownOpenProperty, ValueBoxes.FalseBox); + } + else + { + if (_disablePopupReopen) + { + _disablePopupReopen = false; + } + else + { + SetSelectedDateTime(); + SetCurrentValue(IsDropDownOpenProperty, ValueBoxes.TrueBox); + } + } + } + + private void SafeSetText(string s) + { + if (string.Compare(Text, s, StringComparison.Ordinal) != 0) + { + SetCurrentValue(TextProperty, s); + } + } + + private DateTime? ParseText(string text) + { + try + { + return DateTime.Parse(text); + } + catch + { + // ignored + } + + return null; + } + + private DateTime? SetTextBoxValue(string s) + { + if (string.IsNullOrEmpty(s)) + { + SafeSetText(s); + return SelectedDateTime; + } + + var d = ParseText(s); + + if (d != null) + { + SafeSetText(DateTimeToString((DateTime)d)); + return d; + } + + if (SelectedDateTime != null) + { + var newtext = DateTimeToString(SelectedDateTime.Value); + SafeSetText(newtext); + return SelectedDateTime; + } + SafeSetText(DateTimeToString(DisplayDateTime)); + return DisplayDateTime; + } + + private void SetSelectedDateTime() + { + if (_textBox != null) + { + if (!string.IsNullOrEmpty(_textBox.Text)) + { + var s = _textBox.Text; + + if (SelectedDateTime != null) + { + var selectedTime = DateTimeToString(SelectedDateTime.Value); + + if (string.Compare(selectedTime, s, StringComparison.Ordinal) == 0) + { + return; + } + } + + var d = SetTextBoxValue(s); + if (!SelectedDateTime.Equals(d)) + { + SetCurrentValue(SelectedDateTimeProperty, d); + SetCurrentValue(DisplayDateTimeProperty, d); + } + } + else + { + if (SelectedDateTime.HasValue) + { + SetCurrentValue(SelectedDateTimeProperty, null); + } + } + } + else + { + var d = SetTextBoxValue(_defaultText); + if (!SelectedDateTime.Equals(d)) + { + SetCurrentValue(SelectedDateTimeProperty, d); + } + } + } + + private string DateTimeToString(DateTime d) => d.ToString(DateTimeFormat); + + private static void OnGotFocus(object sender, RoutedEventArgs e) + { + var picker = (DateTimePicker)sender; + if (!e.Handled && picker._textBox != null) + { + if (Equals(e.OriginalSource, picker)) + { + picker._textBox.Focus(); + e.Handled = true; + } + else if (Equals(e.OriginalSource, picker._textBox)) + { + picker._textBox.SelectAll(); + e.Handled = true; + } + } + } + + #endregion + } +} \ No newline at end of file diff --git a/HandyControl/Controls/Input/TimePicker.cs b/HandyControl/Controls/Input/TimePicker.cs index d9c2648b..25d005de 100644 --- a/HandyControl/Controls/Input/TimePicker.cs +++ b/HandyControl/Controls/Input/TimePicker.cs @@ -18,28 +18,36 @@ namespace HandyControl.Controls [TemplatePart(Name = ElementTextBox, Type = typeof(WatermarkTextBox))] [TemplatePart(Name = ElementButton, Type = typeof(Button))] [TemplatePart(Name = ElementPopup, Type = typeof(Popup))] - [TemplatePart(Name = ElementClock, Type = typeof(Clock))] public class TimePicker : Control, IDataInput { #region Constants private const string ElementRoot = "PART_Root"; + private const string ElementTextBox = "PART_TextBox"; + private const string ElementButton = "PART_Button"; + private const string ElementPopup = "PART_Popup"; - private const string ElementClock = "PART_Clock"; #endregion Constants #region Data private Clock _clock; + private string _defaultText; + private ButtonBase _dropDownButton; + private Popup _popUp; + private bool _disablePopupReopen; + private WatermarkTextBox _textBox; + private IDictionary _isHandlerSuspended; + private DateTime? _originalSelectedTime; #endregion Data @@ -71,10 +79,12 @@ namespace HandyControl.Controls public TimePicker() { + InitClock(); CommandBindings.Add(new CommandBinding(ControlCommands.Clear, (s, e) => { ClearValue(SelectedTimeProperty); ClearValue(TextProperty); + _textBox.Text = string.Empty; })); } @@ -142,7 +152,7 @@ namespace HandyControl.Controls "IsDropDownOpen", typeof(bool), typeof(TimePicker), - new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnIsDropDownOpenChanged, OnCoerceIsDropDownOpen)); + new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnIsDropDownOpenChanged, OnCoerceIsDropDownOpen)); private static object OnCoerceIsDropDownOpen(DependencyObject d, object baseValue) => d is TimePicker dp && !dp.IsEnabled ? false : baseValue; @@ -334,7 +344,7 @@ namespace HandyControl.Controls if (DesignerProperties.GetIsInDesignMode(this)) return; if (_popUp != null) { - _popUp.RemoveHandler(PreviewMouseLeftButtonDownEvent, new MouseButtonEventHandler(PopUp_PreviewMouseLeftButtonDown)); + _popUp.PreviewMouseLeftButtonDown -= PopUp_PreviewMouseLeftButtonDown; _popUp.Opened -= PopUp_Opened; _popUp.Closed -= PopUp_Closed; _popUp.Child = null; @@ -343,36 +353,25 @@ namespace HandyControl.Controls if (_dropDownButton != null) { _dropDownButton.Click -= DropDownButton_Click; - _dropDownButton.RemoveHandler(MouseLeaveEvent, new MouseEventHandler(DropDownButton_MouseLeave)); + _dropDownButton.MouseLeave -= DropDownButton_MouseLeave; } if (_textBox != null) { - _textBox.RemoveHandler(KeyDownEvent, new KeyEventHandler(TextBox_KeyDown)); - _textBox.RemoveHandler(TextBoxBase.TextChangedEvent, new TextChangedEventHandler(TextBox_TextChanged)); - _textBox.RemoveHandler(LostFocusEvent, new RoutedEventHandler(TextBox_LostFocus)); - } - - if (_clock != null) - { - _clock.RemoveHandler(Clock.SelectedTimeChangedEvent, new EventHandler>(Clock_SelectedTimeChangedEvent)); - _clock.Confirmed -= Clock_Confirmed; + _textBox.KeyDown -= TextBox_KeyDown; + _textBox.TextChanged -= TextBox_TextChanged; + _textBox.LostFocus -= TextBox_LostFocus; } base.OnApplyTemplate(); - _clock = GetTemplateChild(ElementClock) as Clock; _popUp = GetTemplateChild(ElementPopup) as Popup; _dropDownButton = GetTemplateChild(ElementButton) as Button; _textBox = GetTemplateChild(ElementTextBox) as WatermarkTextBox; CheckNull(); - _clock.ApplyTemplate(); - _clock.AddHandler(Clock.SelectedTimeChangedEvent, new EventHandler>(Clock_SelectedTimeChangedEvent)); - _clock.Confirmed += Clock_Confirmed; - - _popUp.AddHandler(PreviewMouseLeftButtonDownEvent, new MouseButtonEventHandler(PopUp_PreviewMouseLeftButtonDown)); + _popUp.PreviewMouseLeftButtonDown += PopUp_PreviewMouseLeftButtonDown; _popUp.Opened += PopUp_Opened; _popUp.Closed += PopUp_Closed; _popUp.Child = _clock; @@ -383,14 +382,14 @@ namespace HandyControl.Controls } _dropDownButton.Click += DropDownButton_Click; - _dropDownButton.AddHandler(MouseLeaveEvent, new MouseEventHandler(DropDownButton_MouseLeave), true); + _dropDownButton.MouseLeave += DropDownButton_MouseLeave; if (SelectedTime == null) { _textBox.Text = DateTime.Now.ToString(TimeFormat); } - _textBox.AddHandler(KeyDownEvent, new KeyEventHandler(TextBox_KeyDown), true); - _textBox.AddHandler(TextBoxBase.TextChangedEvent, new TextChangedEventHandler(TextBox_TextChanged), true); - _textBox.AddHandler(LostFocusEvent, new RoutedEventHandler(TextBox_LostFocus), true); + _textBox.KeyDown += TextBox_KeyDown; + _textBox.TextChanged += TextBox_TextChanged; + _textBox.LostFocus += TextBox_LostFocus; if (SelectedTime == null) { @@ -436,10 +435,20 @@ namespace HandyControl.Controls private void CheckNull() { - if (_clock == null || _dropDownButton == null || _popUp == null || _textBox == null) + if (_dropDownButton == null || _popUp == null || _textBox == null) throw new Exception(); } + private void InitClock() + { + _clock = new Clock + { + ShowConfirmButton = true + }; + _clock.SelectedTimeChanged += Clock_SelectedTimeChanged; + _clock.Confirmed += Clock_Confirmed; + } + private void TextBox_LostFocus(object sender, RoutedEventArgs e) { SetSelectedTime(); @@ -540,7 +549,7 @@ namespace HandyControl.Controls } } - private void Clock_SelectedTimeChangedEvent(object sender, FunctionEventArgs e) => SelectedTime = e.Info; + private void Clock_SelectedTimeChanged(object sender, FunctionEventArgs e) => SelectedTime = e.Info; private void Clock_Confirmed() => TogglePopUp(); diff --git a/HandyControl/Controls/Time/CalendarWithClock.cs b/HandyControl/Controls/Time/CalendarWithClock.cs new file mode 100644 index 00000000..e8e2c353 --- /dev/null +++ b/HandyControl/Controls/Time/CalendarWithClock.cs @@ -0,0 +1,260 @@ +using System; +using System.Collections.Generic; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; +using HandyControl.Data; + +namespace HandyControl.Controls +{ + [TemplatePart(Name = ElementButtonConfirm, Type = typeof(Button))] + [TemplatePart(Name = ElementClockPresenter, Type = typeof(ContentPresenter))] + [TemplatePart(Name = ElementCalendarPresenter, Type = typeof(ContentPresenter))] + public class CalendarWithClock : Control + { + #region Constants + + private const string ElementButtonConfirm = "PART_ButtonConfirm"; + + private const string ElementClockPresenter = "PART_ClockPresenter"; + + private const string ElementCalendarPresenter = "PART_CalendarPresenter"; + + #endregion Constants + + #region Data + + private ContentPresenter _clockPresenter; + + private ContentPresenter _calendarPresenter; + + private Clock _clock; + + private Calendar _calendar; + + private Button _buttonConfirm; + + private bool _isLoaded; + + private IDictionary _isHandlerSuspended; + + #endregion Data + + #region Public Events + + public static readonly RoutedEvent SelectedDateTimeChangedEvent = + EventManager.RegisterRoutedEvent("SelectedDateTimeChanged", RoutingStrategy.Direct, + typeof(EventHandler>), typeof(CalendarWithClock)); + + public event EventHandler> SelectedDateTimeChanged + { + add => AddHandler(SelectedDateTimeChangedEvent, value); + remove => RemoveHandler(SelectedDateTimeChangedEvent, value); + } + + public event EventHandler> DisplayDateTimeChanged; + + public event Action Confirmed; + + #endregion Public Events + + public CalendarWithClock() + { + InitCalendarAndClock(); + Loaded += (s, e) => + { + if (_isLoaded) return; + _isLoaded = true; + DisplayDateTime = SelectedDateTime ?? DateTime.Now; + }; + } + + #region Public Properties + + public static readonly DependencyProperty DateTimeFormatProperty = DependencyProperty.Register( + "DateTimeFormat", typeof(string), typeof(CalendarWithClock), new PropertyMetadata("yyyy-MM-dd HH:mm:ss")); + + public string DateTimeFormat + { + get => (string)GetValue(DateTimeFormatProperty); + set => SetValue(DateTimeFormatProperty, value); + } + + public static readonly DependencyProperty ShowConfirmButtonProperty = DependencyProperty.Register( + "ShowConfirmButton", typeof(bool), typeof(CalendarWithClock), new PropertyMetadata(ValueBoxes.FalseBox)); + + public bool ShowConfirmButton + { + get => (bool)GetValue(ShowConfirmButtonProperty); + set => SetValue(ShowConfirmButtonProperty, value); + } + + public static readonly DependencyProperty SelectedDateTimeProperty = DependencyProperty.Register( + "SelectedDateTime", typeof(DateTime?), typeof(CalendarWithClock), new PropertyMetadata(default(DateTime?), OnSelectedDateTimeChanged)); + + private static void OnSelectedDateTimeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var ctl = (CalendarWithClock)d; + var v = (DateTime?)e.NewValue; + ctl.OnSelectedDateTimeChanged(new FunctionEventArgs(SelectedDateTimeChangedEvent, ctl) + { + Info = v + }); + } + + public DateTime? SelectedDateTime + { + get => (DateTime?)GetValue(SelectedDateTimeProperty); + set => SetValue(SelectedDateTimeProperty, value); + } + + public static readonly DependencyProperty DisplayDateTimeProperty = DependencyProperty.Register( + "DisplayDateTime", typeof(DateTime), typeof(CalendarWithClock), new FrameworkPropertyMetadata(DateTime.MinValue, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnDisplayDateTimeChanged)); + + private static void OnDisplayDateTimeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var ctl = (CalendarWithClock)d; + if (ctl.IsHandlerSuspended(DisplayDateTimeProperty)) return; + var v = (DateTime)e.NewValue; + ctl._clock.SelectedTime = v; + ctl._calendar.SelectedDate = v; + ctl.OnDisplayDateTimeChanged(new FunctionEventArgs(v)); + } + + public DateTime DisplayDateTime + { + get => (DateTime)GetValue(DisplayDateTimeProperty); + set => SetValue(DisplayDateTimeProperty, value); + } + + #endregion + + #region Public Methods + + public override void OnApplyTemplate() + { + if (_buttonConfirm != null) + { + _buttonConfirm.Click -= ButtonConfirm_OnClick; + } + + base.OnApplyTemplate(); + + _buttonConfirm = GetTemplateChild(ElementButtonConfirm) as Button; + _clockPresenter = GetTemplateChild(ElementClockPresenter) as ContentPresenter; + _calendarPresenter = GetTemplateChild(ElementCalendarPresenter) as ContentPresenter; + + CheckNull(); + + _clockPresenter.Content = _clock; + _calendarPresenter.Content = _calendar; + + _buttonConfirm.Click += ButtonConfirm_OnClick; + } + + #endregion + + #region Protected Methods + + protected virtual void OnSelectedDateTimeChanged(FunctionEventArgs e) => RaiseEvent(e); + + protected virtual void OnDisplayDateTimeChanged(FunctionEventArgs e) + { + var handler = DisplayDateTimeChanged; + handler?.Invoke(this, e); + } + + #endregion Protected Methods + + #region Private Methods + + private void SetIsHandlerSuspended(DependencyProperty property, bool value) + { + if (value) + { + if (_isHandlerSuspended == null) + { + _isHandlerSuspended = new Dictionary(2); + } + + _isHandlerSuspended[property] = true; + } + else + { + _isHandlerSuspended?.Remove(property); + } + } + + private void SetValueNoCallback(DependencyProperty property, object value) + { + SetIsHandlerSuspended(property, true); + try + { + SetCurrentValue(property, value); + } + finally + { + SetIsHandlerSuspended(property, false); + } + } + + private bool IsHandlerSuspended(DependencyProperty property) + { + return _isHandlerSuspended != null && _isHandlerSuspended.ContainsKey(property); + } + + private void CheckNull() + { + if (_buttonConfirm == null || _clockPresenter == null || _calendarPresenter == null) throw new Exception(); + } + + private void ButtonConfirm_OnClick(object sender, RoutedEventArgs e) + { + SelectedDateTime = DisplayDateTime; + Confirmed?.Invoke(); + } + + private void InitCalendarAndClock() + { + _clock = new Clock + { + BorderThickness = new Thickness(), + Background = Brushes.Transparent + }; + TitleElement.SetBackground(_clock, Brushes.Transparent); + _clock.DisplayTimeChanged += Clock_DisplayTimeChanged; + + _calendar = new Calendar + { + BorderThickness = new Thickness(), + Background = Brushes.Transparent, + Focusable = false + }; + TitleElement.SetBackground(_calendar, Brushes.Transparent); + _calendar.SelectedDatesChanged += Calendar_SelectedDatesChanged; + } + + private void Calendar_SelectedDatesChanged(object sender, SelectionChangedEventArgs e) + { + Mouse.Capture(null); + UpdateDisplayTime(); + } + + private void Clock_DisplayTimeChanged(object sender, FunctionEventArgs e) => UpdateDisplayTime(); + + private void UpdateDisplayTime() + { + if (_calendar.SelectedDate != null) + { + var date = _calendar.SelectedDate.Value; + var time = _clock.DisplayTime; + + var result = new DateTime(date.Year, date.Month, date.Day, time.Hour, time.Minute, time.Second); + SetValueNoCallback(DisplayDateTimeProperty, result); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/HandyControl/Controls/Clock/Clock.cs b/HandyControl/Controls/Time/Clock/Clock.cs similarity index 85% rename from HandyControl/Controls/Clock/Clock.cs rename to HandyControl/Controls/Time/Clock/Clock.cs index 647c5d79..ca43b8da 100644 --- a/HandyControl/Controls/Clock/Clock.cs +++ b/HandyControl/Controls/Time/Clock/Clock.cs @@ -9,7 +9,6 @@ using System.Windows.Media; using HandyControl.Data; using HandyControl.Tools; -// ReSharper disable once CheckNamespace namespace HandyControl.Controls { [TemplatePart(Name = ElementButtonAm, Type = typeof(RadioButton))] @@ -61,8 +60,6 @@ namespace HandyControl.Controls private int _secValue; - private bool _isLoaded; - private bool _appliedTemplate; #endregion Data @@ -79,22 +76,12 @@ namespace HandyControl.Controls remove => RemoveHandler(SelectedTimeChangedEvent, value); } - public event EventHandler> DisplayTimeChanged; + public event EventHandler> DisplayTimeChanged; public event Action Confirmed; #endregion Public Events - public Clock() - { - Loaded += (s, e) => - { - if (_isLoaded) return; - _isLoaded = true; - DisplayTime = DateTime.Now; - }; - } - #region Public Properties public static readonly DependencyProperty SelectedTimeProperty = DependencyProperty.Register( @@ -104,6 +91,7 @@ namespace HandyControl.Controls { var ctl = (Clock)d; var v = (DateTime?)e.NewValue; + ctl.DisplayTime = v ?? DateTime.Now; ctl.OnSelectedTimeChanged(new FunctionEventArgs(SelectedTimeChangedEvent, ctl) { Info = v @@ -135,14 +123,14 @@ namespace HandyControl.Controls } public static readonly DependencyProperty DisplayTimeProperty = DependencyProperty.Register( - "DisplayTime", typeof(DateTime), typeof(Clock), new FrameworkPropertyMetadata(DateTime.MinValue, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnDisplayTimeChanged)); + "DisplayTime", typeof(DateTime), typeof(Clock), new FrameworkPropertyMetadata(DateTime.Now, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnDisplayTimeChanged)); private static void OnDisplayTimeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var ctl = (Clock) d; var v = (DateTime) e.NewValue; ctl.Update(v); - ctl.OnDisplayTimeChanged(new FunctionEventArgs(v)); + ctl.OnDisplayTimeChanged(new FunctionEventArgs(v)); } public DateTime DisplayTime @@ -187,16 +175,31 @@ namespace HandyControl.Controls public override void OnApplyTemplate() { _appliedTemplate = false; - _buttonAm?.RemoveHandler(ButtonBase.ClickEvent, new RoutedEventHandler(ButtonAm_OnClick)); - _buttonPm?.RemoveHandler(ButtonBase.ClickEvent, new RoutedEventHandler(ButtonPm_OnClick)); - _buttonConfirm?.RemoveHandler(ButtonBase.ClickEvent, new RoutedEventHandler(ButtonConfirm_OnClick)); - _borderTitle?.RemoveHandler(MouseWheelEvent, new MouseWheelEventHandler(BorderTitle_OnMouseWheel)); + if (_buttonAm != null) + { + _buttonAm.Click -= ButtonAm_OnClick; + } + + if (_buttonPm != null) + { + _buttonPm.Click -= ButtonPm_OnClick; + } + + if (_buttonConfirm != null) + { + _buttonConfirm.Click -= ButtonConfirm_OnClick; + } + + if (_borderTitle != null) + { + _borderTitle.MouseWheel -= BorderTitle_OnMouseWheel; + } if (_canvas != null) { - _canvas.RemoveHandler(MouseWheelEvent, new MouseWheelEventHandler(MyCanvas_OnMouseWheel)); - _canvas.RemoveHandler(ButtonBase.ClickEvent, new RoutedEventHandler(MyCanvas_OnClick)); - _canvas.RemoveHandler(MouseMoveEvent, new MouseEventHandler(MyCanvas_OnMouseMove)); + _canvas.MouseWheel -= Canvas_OnMouseWheel; + _canvas.RemoveHandler(ButtonBase.ClickEvent, new RoutedEventHandler(Canvas_OnClick)); + _canvas.MouseMove -= Canvas_OnMouseMove; } base.OnApplyTemplate(); @@ -212,14 +215,14 @@ namespace HandyControl.Controls CheckNull(); - _buttonAm.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(ButtonAm_OnClick)); - _buttonPm.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(ButtonPm_OnClick)); - _buttonConfirm.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(ButtonConfirm_OnClick)); - _borderTitle.AddHandler(MouseWheelEvent, new MouseWheelEventHandler(BorderTitle_OnMouseWheel)); + _buttonAm.Click += ButtonAm_OnClick; + _buttonPm.Click += ButtonPm_OnClick; + _buttonConfirm.Click += ButtonConfirm_OnClick; + _borderTitle.MouseWheel += BorderTitle_OnMouseWheel; - _canvas.AddHandler(MouseWheelEvent, new MouseWheelEventHandler(MyCanvas_OnMouseWheel)); - _canvas.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(MyCanvas_OnClick)); - _canvas.AddHandler(MouseMoveEvent, new MouseEventHandler(MyCanvas_OnMouseMove)); + _canvas.MouseWheel += Canvas_OnMouseWheel; + _canvas.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(Canvas_OnClick)); + _canvas.MouseMove += Canvas_OnMouseMove; _rotateTransformClock = new RotateTransform(); _borderClock.RenderTransform = _rotateTransformClock; @@ -239,9 +242,14 @@ namespace HandyControl.Controls } _appliedTemplate = true; - if (_isLoaded) + if (SelectedTime.HasValue) { - Update(SelectedTime ?? DisplayTime); + Update(SelectedTime.Value); + } + else + { + DisplayTime = DateTime.Now; + Update(DisplayTime); } } @@ -251,7 +259,7 @@ namespace HandyControl.Controls protected virtual void OnSelectedTimeChanged(FunctionEventArgs e) => RaiseEvent(e); - protected virtual void OnDisplayTimeChanged(FunctionEventArgs e) + protected virtual void OnDisplayTimeChanged(FunctionEventArgs e) { var handler = DisplayTimeChanged; handler?.Invoke(this, e); @@ -284,7 +292,7 @@ namespace HandyControl.Controls e.Handled = true; } - private void MyCanvas_OnMouseWheel(object sender, MouseWheelEventArgs e) + private void Canvas_OnMouseWheel(object sender, MouseWheelEventArgs e) { var value = (int)_rotateTransformClock.Angle; if (e.Delta < 0) @@ -305,7 +313,7 @@ namespace HandyControl.Controls e.Handled = true; } - private void MyCanvas_OnClick(object sender, RoutedEventArgs e) + private void Canvas_OnClick(object sender, RoutedEventArgs e) { _currentButton = e.OriginalSource as ClockRadioButton; if (_currentButton != null) @@ -314,7 +322,7 @@ namespace HandyControl.Controls } } - private void MyCanvas_OnMouseMove(object sender, MouseEventArgs e) + private void Canvas_OnMouseMove(object sender, MouseEventArgs e) { if (e.LeftButton == MouseButtonState.Pressed) { @@ -359,7 +367,7 @@ namespace HandyControl.Controls /// 更新 /// /// - private void Update(DateTime time) + internal void Update(DateTime time) { if (!_appliedTemplate) return; var h = time.Hour; diff --git a/HandyControl/Controls/Clock/ClockRadioButton.cs b/HandyControl/Controls/Time/Clock/ClockRadioButton.cs similarity index 100% rename from HandyControl/Controls/Clock/ClockRadioButton.cs rename to HandyControl/Controls/Time/Clock/ClockRadioButton.cs diff --git a/HandyControl/Controls/TimeBar/SpeTextBlock.cs b/HandyControl/Controls/Time/TimeBar/SpeTextBlock.cs similarity index 100% rename from HandyControl/Controls/TimeBar/SpeTextBlock.cs rename to HandyControl/Controls/Time/TimeBar/SpeTextBlock.cs diff --git a/HandyControl/Controls/TimeBar/TimeBar.cs b/HandyControl/Controls/Time/TimeBar/TimeBar.cs similarity index 100% rename from HandyControl/Controls/TimeBar/TimeBar.cs rename to HandyControl/Controls/Time/TimeBar/TimeBar.cs diff --git a/HandyControl/HandyControl.csproj b/HandyControl/HandyControl.csproj index 11a33412..60886f13 100644 --- a/HandyControl/HandyControl.csproj +++ b/HandyControl/HandyControl.csproj @@ -43,17 +43,20 @@ + - - + + + + @@ -121,9 +124,9 @@ - + - + @@ -260,6 +263,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -356,6 +363,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -392,6 +403,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile diff --git a/HandyControl/Themes/Styles/Base/DateTimePickerBaseStyle.xaml b/HandyControl/Themes/Styles/Base/DateTimePickerBaseStyle.xaml new file mode 100644 index 00000000..8da97a44 --- /dev/null +++ b/HandyControl/Themes/Styles/Base/DateTimePickerBaseStyle.xaml @@ -0,0 +1,338 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + +