modified the pr

This commit is contained in:
NaBian committed 2019-05-12 20:20:04 +08:00
1 parent 4960cdfd94
commit 583c641302
18 files changed
+395 -974

No files matched your search

@@ -99,15 +99,6 @@ namespace HandyControl.Controls
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)));
@@ -34,8 +34,6 @@ namespace HandyControl.Controls
#region Data
private Clock _clock;
private string _defaultText;
private ButtonBase _dropDownButton;
@@ -79,7 +77,7 @@ namespace HandyControl.Controls
public TimePicker()
{
InitClock();
Clock = new Clock();
CommandBindings.Add(new CommandBinding(ControlCommands.Clear, (s, e) =>
{
ClearValue(SelectedTimeProperty);
@@ -103,18 +101,6 @@ namespace HandyControl.Controls
#endregion TimeFormat
#region ClockStyle
public Style ClockStyle
{
get => (Style)GetValue(ClockStyleProperty);
set => SetValue(ClockStyleProperty, value);
}
public static readonly DependencyProperty ClockStyleProperty = DependencyProperty.Register("ClockStyle", typeof(Style), typeof(TimePicker));
#endregion CalendarStyle
#region DisplayTime
public DateTime DisplayTime
@@ -133,8 +119,8 @@ namespace HandyControl.Controls
private static object CoerceDisplayTime(DependencyObject d, object value)
{
var dp = (TimePicker)d;
dp._clock.DisplayTime = (DateTime)value;
return dp._clock.DisplayTime;
dp.Clock.DisplayTime = (DateTime)value;
return dp.Clock.DisplayTime;
}
#endregion DisplayTime
@@ -170,7 +156,7 @@ namespace HandyControl.Controls
dp.Dispatcher.BeginInvoke(DispatcherPriority.Input, (Action)delegate
{
dp._clock.Focus();
dp.Clock.Focus();
});
}
}
@@ -212,8 +198,8 @@ namespace HandyControl.Controls
private static object CoerceSelectedTime(DependencyObject d, object value)
{
var dp = (TimePicker)d;
dp._clock.SelectedTime = (DateTime?)value;
return dp._clock.SelectedTime;
dp.Clock.SelectedTime = (DateTime?)value;
return dp.Clock.SelectedTime;
}
#endregion SelectedDate
@@ -306,6 +292,35 @@ namespace HandyControl.Controls
set => SetValue(ShowClearButtonProperty, value);
}
public static readonly DependencyProperty ClockProperty = DependencyProperty.Register(
"Clock", typeof(ClockBase), typeof(TimePicker), new FrameworkPropertyMetadata(default(Clock), FrameworkPropertyMetadataOptions.NotDataBindable, OnClockChanged));
private static void OnClockChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (TimePicker) d;
var oldClock = e.OldValue as ClockBase;
var newClock = e.NewValue as ClockBase;
if (oldClock != null)
{
oldClock.SelectedTimeChanged -= ctl.Clock_SelectedTimeChanged;
oldClock.Confirmed -= ctl.Clock_Confirmed;
}
if (newClock != null)
{
newClock.ShowConfirmButton = true;
newClock.SelectedTimeChanged += ctl.Clock_SelectedTimeChanged;
newClock.Confirmed += ctl.Clock_Confirmed;
}
}
public ClockBase Clock
{
get => (ClockBase) GetValue(ClockProperty);
set => SetValue(ClockProperty, value);
}
#endregion Public Properties
#region Public Methods
@@ -374,7 +389,7 @@ namespace HandyControl.Controls
_popUp.PreviewMouseLeftButtonDown += PopUp_PreviewMouseLeftButtonDown;
_popUp.Opened += PopUp_Opened;
_popUp.Closed += PopUp_Closed;
_popUp.Child = _clock;
_popUp.Child = Clock;
if (IsDropDownOpen)
{
@@ -439,20 +454,7 @@ namespace HandyControl.Controls
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();
}
private void TextBox_LostFocus(object sender, RoutedEventArgs e) => SetSelectedTime();
private void SetIsHandlerSuspended(DependencyProperty property, bool value)
{
@@ -560,7 +562,7 @@ namespace HandyControl.Controls
SetCurrentValue(IsDropDownOpenProperty, ValueBoxes.TrueBox);
}
_clock?.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
Clock?.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
OnClockOpened(new RoutedEventArgs());
}
@@ -572,7 +574,7 @@ namespace HandyControl.Controls
SetCurrentValue(IsDropDownOpenProperty, ValueBoxes.FalseBox);
}
if (_clock.IsKeyboardFocusWithin)
if (Clock.IsKeyboardFocusWithin)
{
MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
}
@@ -192,7 +192,7 @@ namespace HandyControl.Controls
/// <summary>
/// 当前垂直滚动偏移
/// </summary>
private static readonly DependencyProperty CurrentVerticalOffsetProperty = DependencyProperty.Register(
internal static readonly DependencyProperty CurrentVerticalOffsetProperty = DependencyProperty.Register(
"CurrentVerticalOffset", typeof(double), typeof(ScrollViewer), new PropertyMetadata(ValueBoxes.Double0Box, OnCurrentVerticalOffsetChanged));
private static void OnCurrentVerticalOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
@@ -206,7 +206,7 @@ namespace HandyControl.Controls
/// <summary>
/// 当前垂直滚动偏移
/// </summary>
private double CurrentVerticalOffset
internal double CurrentVerticalOffset
{
// ReSharper disable once UnusedMember.Local
get => (double) GetValue(CurrentVerticalOffsetProperty);
@@ -216,7 +216,7 @@ namespace HandyControl.Controls
/// <summary>
/// 当前水平滚动偏移
/// </summary>
public static readonly DependencyProperty CurrentHorizontalOffsetProperty = DependencyProperty.Register(
internal static readonly DependencyProperty CurrentHorizontalOffsetProperty = DependencyProperty.Register(
"CurrentHorizontalOffset", typeof(double), typeof(ScrollViewer), new PropertyMetadata(ValueBoxes.Double0Box, OnCurrentHorizontalOffsetChanged));
private static void OnCurrentHorizontalOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
@@ -230,7 +230,7 @@ namespace HandyControl.Controls
/// <summary>
/// 当前水平滚动偏移
/// </summary>
public double CurrentHorizontalOffset
internal double CurrentHorizontalOffset
{
get => (double) GetValue(CurrentHorizontalOffsetProperty);
set => SetValue(CurrentHorizontalOffsetProperty, value);
@@ -6,26 +6,23 @@ using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using HandyControl.Data;
using HandyControl.Tools;
namespace HandyControl.Controls
{
[TemplatePart(Name = ElementButtonAm, Type = typeof(RadioButton))]
[TemplatePart(Name = ElementButtonPm, Type = typeof(RadioButton))]
[TemplatePart(Name = ElementButtonConfirm, Type = typeof(Button))]
[TemplatePart(Name = ElementCanvas, Type = typeof(Canvas))]
[TemplatePart(Name = ElementBorderTitle, Type = typeof(Border))]
[TemplatePart(Name = ElementBorderClock, Type = typeof(Border))]
[TemplatePart(Name = ElementPanelNum, Type = typeof(CirclePanel))]
[TemplatePart(Name = ElementTimeStr, Type = typeof(TextBlock))]
public class Clock : Control
public class Clock : ClockBase
{
#region Constants
private const string ElementButtonAm = "PART_ButtonAm";
private const string ElementButtonPm = "PART_ButtonPm";
private const string ElementButtonConfirm = "PART_ButtonConfirm";
private const string ElementCanvas = "PART_Canvas";
private const string ElementBorderTitle = "PART_BorderTitle";
private const string ElementBorderClock = "PART_BorderClock";
@@ -40,8 +37,6 @@ namespace HandyControl.Controls
private RadioButton _buttonPm;
private Button _buttonConfirm;
private Canvas _canvas;
private Border _borderTitle;
@@ -60,59 +55,10 @@ namespace HandyControl.Controls
private int _secValue;
private bool _appliedTemplate;
#endregion Data
#region Public Events
public static readonly RoutedEvent SelectedTimeChangedEvent =
EventManager.RegisterRoutedEvent("SelectedTimeChanged", RoutingStrategy.Direct,
typeof(EventHandler<FunctionEventArgs<DateTime?>>), typeof(Clock));
public event EventHandler<FunctionEventArgs<DateTime?>> SelectedTimeChanged
{
add => AddHandler(SelectedTimeChangedEvent, value);
remove => RemoveHandler(SelectedTimeChangedEvent, value);
}
public event EventHandler<FunctionEventArgs<DateTime>> DisplayTimeChanged;
public event Action Confirmed;
#endregion Public Events
#region Public Properties
public static readonly DependencyProperty SelectedTimeProperty = DependencyProperty.Register(
"SelectedTime", typeof(DateTime?), typeof(Clock), new PropertyMetadata(default(DateTime?), OnSelectedTimeChanged));
private static void OnSelectedTimeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (Clock)d;
var v = (DateTime?)e.NewValue;
ctl.DisplayTime = v ?? DateTime.Now;
ctl.OnSelectedTimeChanged(new FunctionEventArgs<DateTime?>(SelectedTimeChangedEvent, ctl)
{
Info = v
});
}
public DateTime? SelectedTime
{
get => (DateTime?) GetValue(SelectedTimeProperty);
set => SetValue(SelectedTimeProperty, value);
}
public static readonly DependencyProperty TimeFormatProperty = DependencyProperty.Register(
"TimeFormat", typeof(string), typeof(Clock), new PropertyMetadata("HH:mm:ss"));
public string TimeFormat
{
get => (string) GetValue(TimeFormatProperty);
set => SetValue(TimeFormatProperty, value);
}
public static readonly DependencyProperty ClockRadioButtonStyleProperty = DependencyProperty.Register(
"ClockRadioButtonStyle", typeof(Style), typeof(Clock), new PropertyMetadata(default(Style)));
@@ -122,32 +68,6 @@ namespace HandyControl.Controls
set => SetValue(ClockRadioButtonStyleProperty, value);
}
public static readonly DependencyProperty DisplayTimeProperty = DependencyProperty.Register(
"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<DateTime>(v));
}
public DateTime DisplayTime
{
get => (DateTime) GetValue(DisplayTimeProperty);
set => SetValue(DisplayTimeProperty, value);
}
internal static readonly DependencyProperty ShowConfirmButtonProperty = DependencyProperty.Register(
"ShowConfirmButton", typeof(bool), typeof(Clock), new PropertyMetadata(ValueBoxes.FalseBox));
internal bool ShowConfirmButton
{
get => (bool)GetValue(ShowConfirmButtonProperty);
set => SetValue(ShowConfirmButtonProperty, value);
}
private int SecValue
{
get => _secValue;
@@ -174,7 +94,7 @@ namespace HandyControl.Controls
public override void OnApplyTemplate()
{
_appliedTemplate = false;
AppliedTemplate = false;
if (_buttonAm != null)
{
_buttonAm.Click -= ButtonAm_OnClick;
@@ -185,9 +105,9 @@ namespace HandyControl.Controls
_buttonPm.Click -= ButtonPm_OnClick;
}
if (_buttonConfirm != null)
if (ButtonConfirm != null)
{
_buttonConfirm.Click -= ButtonConfirm_OnClick;
ButtonConfirm.Click -= ButtonConfirm_OnClick;
}
if (_borderTitle != null)
@@ -206,18 +126,18 @@ namespace HandyControl.Controls
_buttonAm = GetTemplateChild(ElementButtonAm) as RadioButton;
_buttonPm = GetTemplateChild(ElementButtonPm) as RadioButton;
_buttonConfirm = GetTemplateChild(ElementButtonConfirm) as Button;
ButtonConfirm = GetTemplateChild(ElementButtonConfirm) as Button;
_borderTitle = GetTemplateChild(ElementBorderTitle) as Border;
_canvas = GetTemplateChild(ElementCanvas) as Canvas;
_borderClock = GetTemplateChild(ElementBorderClock) as Border;
_circlePanel = GetTemplateChild(ElementPanelNum) as CirclePanel;
_blockTime = GetTemplateChild(ElementTimeStr) as TextBlock;
CheckNull();
if (!CheckNull()) return;
_buttonAm.Click += ButtonAm_OnClick;
_buttonPm.Click += ButtonPm_OnClick;
_buttonConfirm.Click += ButtonConfirm_OnClick;
ButtonConfirm.Click += ButtonConfirm_OnClick;
_borderTitle.MouseWheel += BorderTitle_OnMouseWheel;
_canvas.MouseWheel += Canvas_OnMouseWheel;
@@ -241,7 +161,7 @@ namespace HandyControl.Controls
_circlePanel.Children.Add(button);
}
_appliedTemplate = true;
AppliedTemplate = true;
if (SelectedTime.HasValue)
{
Update(SelectedTime.Value);
@@ -255,26 +175,15 @@ namespace HandyControl.Controls
#endregion Public Methods
#region Protected Methods
protected virtual void OnSelectedTimeChanged(FunctionEventArgs<DateTime?> e) => RaiseEvent(e);
protected virtual void OnDisplayTimeChanged(FunctionEventArgs<DateTime> e)
{
var handler = DisplayTimeChanged;
handler?.Invoke(this, e);
}
#endregion Protected Methods
#region Private Methods
private void CheckNull()
private bool CheckNull()
{
if (_buttonPm == null || _buttonAm == null || _buttonConfirm == null || _canvas == null ||
if (_buttonPm == null || _buttonAm == null || ButtonConfirm == null || _canvas == null ||
_borderTitle == null || _borderClock == null || _circlePanel == null ||
_blockTime == null) throw new Exception();
_blockTime == null) return false;
return true;
}
private void BorderTitle_OnMouseWheel(object sender, MouseWheelEventArgs e)
@@ -339,7 +248,7 @@ namespace HandyControl.Controls
private void Update()
{
if (!_appliedTemplate) return;
if (!AppliedTemplate) return;
var hValue = _currentButton.Num;
if (_buttonPm.IsChecked == true)
{
@@ -367,9 +276,9 @@ namespace HandyControl.Controls
/// 更新
/// </summary>
/// <param name="time"></param>
internal void Update(DateTime time)
internal override void Update(DateTime time)
{
if (!_appliedTemplate) return;
if (!AppliedTemplate) return;
var h = time.Hour;
var m = time.Minute;
@@ -396,12 +305,6 @@ namespace HandyControl.Controls
Update();
}
private void ButtonConfirm_OnClick(object sender, RoutedEventArgs e)
{
SelectedTime = DisplayTime;
Confirmed?.Invoke();
}
/// <summary>
/// 获取显示时间
/// </summary>
@@ -0,0 +1,106 @@
using System;
using System.Windows;
using System.Windows.Controls;
using HandyControl.Data;
namespace HandyControl.Controls
{
[TemplatePart(Name = ElementButtonConfirm, Type = typeof(Button))]
public abstract class ClockBase : Control
{
protected const string ElementButtonConfirm = "PART_ButtonConfirm";
protected Button ButtonConfirm;
protected bool AppliedTemplate;
public event Action Confirmed;
public event EventHandler<FunctionEventArgs<DateTime>> DisplayTimeChanged;
public static readonly RoutedEvent SelectedTimeChangedEvent =
EventManager.RegisterRoutedEvent("SelectedTimeChanged", RoutingStrategy.Direct,
typeof(EventHandler<FunctionEventArgs<DateTime?>>), typeof(ClockBase));
public event EventHandler<FunctionEventArgs<DateTime?>> SelectedTimeChanged
{
add => AddHandler(SelectedTimeChangedEvent, value);
remove => RemoveHandler(SelectedTimeChangedEvent, value);
}
public static readonly DependencyProperty TimeFormatProperty = DependencyProperty.Register(
"TimeFormat", typeof(string), typeof(ClockBase), new PropertyMetadata("HH:mm:ss"));
public string TimeFormat
{
get => (string)GetValue(TimeFormatProperty);
set => SetValue(TimeFormatProperty, value);
}
public static readonly DependencyProperty SelectedTimeProperty = DependencyProperty.Register(
"SelectedTime", typeof(DateTime?), typeof(ClockBase), new PropertyMetadata(default(DateTime?), OnSelectedTimeChanged));
private static void OnSelectedTimeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (ClockBase)d;
var v = (DateTime?)e.NewValue;
ctl.DisplayTime = v ?? DateTime.Now;
ctl.OnSelectedTimeChanged(new FunctionEventArgs<DateTime?>(SelectedTimeChangedEvent, ctl)
{
Info = v
});
}
public DateTime? SelectedTime
{
get => (DateTime?) GetValue(SelectedTimeProperty);
set => SetValue(SelectedTimeProperty, value);
}
public static readonly DependencyProperty DisplayTimeProperty = DependencyProperty.Register(
"DisplayTime", typeof(DateTime), typeof(ClockBase),
new FrameworkPropertyMetadata(DateTime.Now, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
OnDisplayTimeChanged));
private static void OnDisplayTimeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (ClockBase)d;
var v = (DateTime)e.NewValue;
ctl.Update(v);
ctl.OnDisplayTimeChanged(new FunctionEventArgs<DateTime>(v));
}
public DateTime DisplayTime
{
get => (DateTime)GetValue(DisplayTimeProperty);
set => SetValue(DisplayTimeProperty, value);
}
internal static readonly DependencyProperty ShowConfirmButtonProperty = DependencyProperty.Register(
"ShowConfirmButton", typeof(bool), typeof(ClockBase), new PropertyMetadata(ValueBoxes.FalseBox));
internal bool ShowConfirmButton
{
get => (bool) GetValue(ShowConfirmButtonProperty);
set => SetValue(ShowConfirmButtonProperty, value);
}
protected virtual void OnSelectedTimeChanged(FunctionEventArgs<DateTime?> e) => RaiseEvent(e);
protected virtual void OnDisplayTimeChanged(FunctionEventArgs<DateTime> e)
{
var handler = DisplayTimeChanged;
handler?.Invoke(this, e);
}
protected void ButtonConfirm_OnClick(object sender, RoutedEventArgs e)
{
SelectedTime = DisplayTime;
Confirmed?.Invoke();
}
internal abstract void Update(DateTime time);
protected void Clock_SelectedTimeChanged(object sender, FunctionEventArgs<DateTime?> e) => SelectedTime = e.Info;
}
}
@@ -0,0 +1,148 @@
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
namespace HandyControl.Controls
{
[TemplatePart(Name = ElementHourList, Type = typeof(ListBox))]
[TemplatePart(Name = ElementMinuteList, Type = typeof(ListBox))]
[TemplatePart(Name = ElementSecondList, Type = typeof(ListBox))]
public class ListClock : ClockBase
{
#region Constants
private const string ElementHourList = "PART_HourList";
private const string ElementMinuteList = "PART_MinuteList";
private const string ElementSecondList = "PART_SecondList";
#endregion Constants
#region Data
private ListBox _hourList;
private ListBox _minuteList;
private ListBox _secondList;
#endregion Data
public override void OnApplyTemplate()
{
AppliedTemplate = false;
if (ButtonConfirm != null)
{
ButtonConfirm.Click -= ButtonConfirm_OnClick;
}
if (_hourList != null)
{
_hourList.SelectionChanged -= HourList_SelectionChanged;
}
if (_minuteList != null)
{
_minuteList.SelectionChanged -= MinuteList_SelectionChanged;
}
if (_secondList != null)
{
_secondList.SelectionChanged -= SecondList_SelectionChanged;
}
base.OnApplyTemplate();
_hourList = GetTemplateChild(ElementHourList) as ListBox;
if (_hourList != null)
{
CreateItemsSource(_hourList, 24);
_hourList.SelectionChanged += HourList_SelectionChanged;
}
_minuteList = GetTemplateChild(ElementMinuteList) as ListBox;
if (_minuteList != null)
{
CreateItemsSource(_minuteList, 60);
_minuteList.SelectionChanged += MinuteList_SelectionChanged;
}
_secondList = GetTemplateChild(ElementSecondList) as ListBox;
if (_secondList != null)
{
CreateItemsSource(_secondList, 60);
_secondList.SelectionChanged += SecondList_SelectionChanged;
}
ButtonConfirm = GetTemplateChild(ElementButtonConfirm) as Button;
if (ButtonConfirm != null)
{
ButtonConfirm.Click += ButtonConfirm_OnClick;
}
AppliedTemplate = true;
if (SelectedTime.HasValue)
{
Update(SelectedTime.Value);
}
else
{
DisplayTime = DateTime.Now;
Update(DisplayTime);
}
}
private void HourList_SelectionChanged(object sender, SelectionChangedEventArgs e) => Update();
private void MinuteList_SelectionChanged(object sender, SelectionChangedEventArgs e) => Update();
private void SecondList_SelectionChanged(object sender, SelectionChangedEventArgs e) => Update();
private void CreateItemsSource(ItemsControl selector, int count)
{
var list = new List<string>();
for (int i = 0; i < count; i++)
{
list.Add(i.ToString("#00"));
}
selector.ItemsSource = list;
}
private void Update()
{
if (_hourList.SelectedIndex >= 0 && _hourList.SelectedIndex < 24 &&
_minuteList.SelectedIndex >= 0 && _minuteList.SelectedIndex < 60 &&
_secondList.SelectedIndex >= 0 && _secondList.SelectedIndex < 60)
{
var now = DateTime.Now;
DisplayTime = new DateTime(now.Year, now.Month, now.Day, _hourList.SelectedIndex,
_minuteList.SelectedIndex, _secondList.SelectedIndex);
}
}
/// <summary>
/// 更新
/// </summary>
/// <param name="time"></param>
internal override void Update(DateTime time)
{
if (!AppliedTemplate) return;
var h = time.Hour;
var m = time.Minute;
var s = time.Second;
_hourList.SelectedIndex = h;
_minuteList.SelectedIndex = m;
_secondList.SelectedIndex = s;
_hourList.ScrollIntoView(_hourList.SelectedItem);
_minuteList.ScrollIntoView(_minuteList.SelectedItem);
_secondList.ScrollIntoView(_secondList.SelectedItem);
DisplayTime = time;
}
}
}
@@ -1,79 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
namespace HandyControl.Controls
{
/// <summary>
/// ItemsControl扩展方法
/// </summary>
public static class ItemsControlExtensions
{
/// <summary>
/// 平滑滚动至指定元素
/// </summary>
/// <param name="itemsControl"></param>
/// <param name="item"></param>
public static void AnimateScrollIntoView(this ItemsControl itemsControl, object item)
{
ScrollViewer scrollViewer = FindVisualChild<ScrollViewer>(itemsControl);
if (scrollViewer == null)
{
return;
}
UIElement container = itemsControl.ItemContainerGenerator.ContainerFromItem(item) as UIElement;
if (container == null)
{
return;
}
int index = itemsControl.ItemContainerGenerator.IndexFromContainer(container);
//平滑滚动到元素所在位置
//double toValue = scrollViewer.ScrollableHeight * ((double)index / itemsControl.Items.Count);
//平滑滚动,将选中的元素置顶
double toValue = VisualTreeHelper.GetOffset(container).Y;
DoubleAnimation verticalAnimation = new DoubleAnimation();
verticalAnimation.From = scrollViewer.VerticalOffset;
verticalAnimation.To = toValue;
verticalAnimation.DecelerationRatio = .2;
verticalAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(200));
Storyboard storyboard = new Storyboard();
storyboard.Children.Add(verticalAnimation);
Storyboard.SetTarget(verticalAnimation, scrollViewer);
Storyboard.SetTargetProperty(verticalAnimation, new PropertyPath(ScrollViewerBehavior.VerticalOffsetProperty));
storyboard.Begin();
}
/// <summary>
/// 查找元素的子元素
/// </summary>
/// <typeparam name="T">子元素类型</typeparam>
/// <param name="obj"></param>
/// <returns></returns>
public static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
if (child != null && child is T)
return (T)child;
else
{
T childOfChild = FindVisualChild<T>(child);
if (childOfChild != null)
return childOfChild;
}
}
return null;
}
}
}
@@ -1,42 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
namespace HandyControl.Controls
{
public class TimeButton : ListBoxItem
{
#region Private属性
#endregion
#region 依赖属性定义
#endregion
#region 依赖属性set get
#endregion
#region Constructors
static TimeButton()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(TimeButton), new FrameworkPropertyMetadata(typeof(TimeButton)));
}
#endregion
#region Override方法
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
}
#endregion
#region Private方法
#endregion
}
}
@@ -1,114 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
namespace HandyControl.Controls
{
public class TimePickerList : Control
{
#region Private属性
private TextBox PART_TextBox;
private TimeSelector PART_TimeSelector;
private Popup PART_Popup;
#endregion
#region 依赖属性定义
#endregion
#region 依赖属性set get
#region TimeStringFormat
public string TimeStringFormat
{
get { return (string)GetValue(TimeStringFormatProperty); }
set { SetValue(TimeStringFormatProperty, value); }
}
public static readonly DependencyProperty TimeStringFormatProperty =
DependencyProperty.Register("TimeStringFormat", typeof(string), typeof(TimePickerList), new PropertyMetadata("HH:mm:ss"));
#endregion
#region SelectedTime
public DateTime? SelectedTime
{
get { return (DateTime?)GetValue(SelectedTimeProperty); }
set { SetValue(SelectedTimeProperty, value); }
}
public static readonly DependencyProperty SelectedTimeProperty =
DependencyProperty.Register("SelectedTime", typeof(DateTime?), typeof(TimePickerList), new PropertyMetadata(null, SelectedTimeChangedCallback));
private static void SelectedTimeChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TimePickerList timePicker = d as TimePickerList;
DateTime dt = (DateTime)e.NewValue;
timePicker.PART_TimeSelector.SelectedTime = dt;
}
#endregion
#region DropDownHeight
public double DropDownHeight
{
get { return (double)GetValue(DropDownHeightProperty); }
set { SetValue(DropDownHeightProperty, value); }
}
public static readonly DependencyProperty DropDownHeightProperty =
DependencyProperty.Register("DropDownHeight", typeof(double), typeof(TimePickerList), new PropertyMetadata(168d));
#endregion
#endregion
#region Constructors
static TimePickerList()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(TimePickerList), new FrameworkPropertyMetadata(typeof(TimePickerList)));
}
#endregion
#region Override方法
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
this.PART_TextBox = this.GetTemplateChild("PART_TextBox") as TextBox;
this.PART_TimeSelector = this.GetTemplateChild("PART_TimeSelector") as TimeSelector;
this.PART_Popup = this.GetTemplateChild("PART_Popup") as Popup;
if (this.PART_TimeSelector != null)
{
this.PART_TimeSelector.Owner = this;
this.PART_TimeSelector.SelectedTimeChanged += PART_TimeSelector_SelectedTimeChanged;
}
if (this.PART_Popup != null)
{
this.PART_Popup.Opened += PART_Popup_Opened;
}
}
private void PART_Popup_Opened(object sender, EventArgs e)
{
this.PART_TimeSelector.SetButtonSelected();
}
#endregion
#region Private方法
private void PART_TimeSelector_SelectedTimeChanged(object sender, RoutedPropertyChangedEventArgs<DateTime?> e)
{
if (this.PART_TextBox != null && e.NewValue != null)
{
this.PART_TextBox.Text = e.NewValue.Value.ToString(this.TimeStringFormat);
this.SelectedTime = e.NewValue;
}
}
#endregion
}
}
@@ -1,380 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
namespace HandyControl.Controls
{
public class TimeSelector : Control
{
private ObservableCollection<TimeButton> HourButtons = new ObservableCollection<TimeButton>();
private ObservableCollection<TimeButton> MinuteButtons = new ObservableCollection<TimeButton>();
private ObservableCollection<TimeButton> SecondButtons = new ObservableCollection<TimeButton>();
#region 控件内部元素
private ListBox PART_Hour;
private ListBox PART_Minute;
private ListBox PART_Second;
#endregion
#region 私有属性
private int Hour = 0;
private int Minute = 0;
private int Second = 0;
#endregion
#region Fields
public TimePickerList Owner { get; set; }
#endregion
#region 事件定义
#region SelectedTimeChanged
public static readonly RoutedEvent SelectedTimeChangedEvent = EventManager.RegisterRoutedEvent("SelectedTimeChanged",
RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler<DateTime?>), typeof(TimeSelector));
public event RoutedPropertyChangedEventHandler<DateTime?> SelectedTimeChanged
{
add
{
this.AddHandler(SelectedTimeChangedEvent, value);
}
remove
{
this.RemoveHandler(SelectedTimeChangedEvent, value);
}
}
public virtual void OnSelectedTimeChanged(DateTime? oldValue, DateTime? newValue)
{
RoutedPropertyChangedEventArgs<DateTime?> arg = new RoutedPropertyChangedEventArgs<DateTime?>(oldValue, newValue, SelectedTimeChangedEvent);
this.RaiseEvent(arg);
}
#endregion
#endregion
#region 依赖属性set get
#region SelectedTime
public DateTime? SelectedTime
{
get { return (DateTime?)GetValue(SelectedTimeProperty); }
set { SetValue(SelectedTimeProperty, value); }
}
public static readonly DependencyProperty SelectedTimeProperty =
DependencyProperty.Register("SelectedTime", typeof(DateTime?), typeof(TimeSelector), new PropertyMetadata(null, SelectedTimeChangedCallback));
private static void SelectedTimeChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TimeSelector timeSelector = d as TimeSelector;
DateTime dt = (DateTime)e.NewValue;
timeSelector.SetButtonSelected();
timeSelector.OnSelectedTimeChanged((DateTime?)e.OldValue, (DateTime?)e.NewValue);
}
public void SetButtonSelected()
{
if (!this.SelectedTime.HasValue)
{
return;
}
this.Hour = this.SelectedTime.Value.Hour;
this.Minute = this.SelectedTime.Value.Minute;
this.Second = this.SelectedTime.Value.Second;
if (this.PART_Hour != null)
{
for (int i = 0; i < this.PART_Hour.Items.Count; i++)
{
TimeButton timeButton = this.PART_Hour.Items[i] as TimeButton;
if (Convert.ToString(timeButton.Content).Equals(Convert.ToString(this.SelectedTime.Value.Hour)))
{
this.PART_Hour.SelectedIndex = i;
this.PART_Hour.AnimateScrollIntoView(timeButton);
break;
}
}
}
if (this.PART_Minute != null)
{
for (int i = 0; i < this.PART_Minute.Items.Count; i++)
{
TimeButton timeButton = this.PART_Minute.Items[i] as TimeButton;
if (Convert.ToString(timeButton.Content).Equals(Convert.ToString(this.SelectedTime.Value.Minute)))
{
this.PART_Minute.SelectedIndex = i;
this.PART_Minute.AnimateScrollIntoView(timeButton);
break;
}
}
}
if (this.PART_Second != null)
{
for (int i = 0; i < this.PART_Second.Items.Count; i++)
{
TimeButton timeButton = this.PART_Second.Items[i] as TimeButton;
if (Convert.ToString(timeButton.Content).Equals(Convert.ToString(this.SelectedTime.Value.Second)))
{
this.PART_Second.SelectedIndex = i;
this.PART_Second.AnimateScrollIntoView(timeButton);
break;
}
}
}
}
#endregion
#region SelectedHour
public int? SelectedHour
{
get { return (int?)GetValue(SelectedHourProperty); }
set { SetValue(SelectedHourProperty, value); }
}
public static readonly DependencyProperty SelectedHourProperty =
DependencyProperty.Register("SelectedHour", typeof(int?), typeof(TimeSelector), new PropertyMetadata(null, SelectedHourChanged));
private static void SelectedHourChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TimeSelector timeSelector = d as TimeSelector;
timeSelector.Hour = e.NewValue == null ? 0 : (int)e.NewValue;
timeSelector.SetSelectedTime();
}
#endregion
#region SelectedMinute
public int? SelectedMinute
{
get { return (int?)GetValue(SelectedMinuteProperty); }
set { SetValue(SelectedMinuteProperty, value); }
}
public static readonly DependencyProperty SelectedMinuteProperty =
DependencyProperty.Register("SelectedMinute", typeof(int?), typeof(TimeSelector), new PropertyMetadata(null, SelectedMinuteChanged));
private static void SelectedMinuteChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TimeSelector timeSelector = d as TimeSelector;
timeSelector.Minute = e.NewValue == null ? 0 : (int)e.NewValue;
timeSelector.SetSelectedTime();
}
#endregion
#region SelectedSecond
public int? SelectedSecond
{
get { return (int?)GetValue(SelectedSecondProperty); }
set { SetValue(SelectedSecondProperty, value); }
}
public static readonly DependencyProperty SelectedSecondProperty =
DependencyProperty.Register("SelectedSecond", typeof(int?), typeof(TimeSelector), new PropertyMetadata(null, SelectedSecondChanged));
private static void SelectedSecondChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TimeSelector timeSelector = d as TimeSelector;
timeSelector.Second = e.NewValue == null ? 0 : (int)e.NewValue;
timeSelector.SetSelectedTime();
}
#endregion
#region ItemHeight
public double ItemHeight
{
get { return (double)GetValue(ItemHeightProperty); }
set { SetValue(ItemHeightProperty, value); }
}
public static readonly DependencyProperty ItemHeightProperty =
DependencyProperty.Register("ItemHeight", typeof(double), typeof(TimeSelector), new PropertyMetadata(28.0));
#endregion
#endregion
#region Constructors
static TimeSelector()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(TimeSelector), new FrameworkPropertyMetadata(typeof(TimeSelector)));
}
#endregion
#region Override方法
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
this.PART_Hour = this.GetTemplateChild("PART_Hour") as ListBox;
this.PART_Minute = this.GetTemplateChild("PART_Minute") as ListBox;
this.PART_Second = this.GetTemplateChild("PART_Second") as ListBox;
if (this.PART_Hour != null)
{
this.CreateHourButtons();
this.PART_Hour.AddHandler(ListBoxItem.MouseLeftButtonDownEvent, new RoutedEventHandler(HourButton_Click), true);
}
if (this.PART_Minute != null)
{
this.CreateMinuteButtons();
this.PART_Minute.AddHandler(ListBoxItem.MouseLeftButtonDownEvent, new RoutedEventHandler(MinuteButton_Click), true);
}
if (this.PART_Second != null)
{
this.CreateSecondButtons();
this.PART_Second.AddHandler(ListBoxItem.MouseLeftButtonDownEvent, new RoutedEventHandler(SecondButton_Click), true);
}
}
#endregion
#region Private方法
private void MinuteButton_Click(object sender, RoutedEventArgs e)
{
TimeButton selectedItem = this.PART_Minute.SelectedItem as TimeButton;
if (selectedItem == null)
{
return;
}
this.SelectedMinute = Convert.ToInt32(selectedItem.DataContext);
this.PART_Minute.AnimateScrollIntoView(selectedItem);
}
private void SecondButton_Click(object sender, RoutedEventArgs e)
{
TimeButton selectedItem = this.PART_Second.SelectedItem as TimeButton;
if (selectedItem == null)
{
return;
}
this.SelectedSecond = Convert.ToInt32(selectedItem.DataContext);
this.PART_Second.AnimateScrollIntoView(selectedItem);
}
private void HourButton_Click(object sender, RoutedEventArgs e)
{
TimeButton selectedItem = this.PART_Hour.SelectedItem as TimeButton;
if (selectedItem == null)
{
return;
}
this.SelectedHour = Convert.ToInt32(selectedItem.DataContext);
this.PART_Hour.AnimateScrollIntoView(selectedItem);
}
private void CreateHourButtons()
{
this.CreateItems(24, this.HourButtons);
this.CreateExtraItem(this.HourButtons);
this.PART_Hour.ItemsSource = this.HourButtons;
}
private void CreateMinuteButtons()
{
this.CreateItems(60, this.MinuteButtons);
this.CreateExtraItem(this.MinuteButtons);
this.PART_Minute.ItemsSource = this.MinuteButtons;
}
private void CreateSecondButtons()
{
this.CreateItems(60, this.SecondButtons);
this.CreateExtraItem(this.SecondButtons);
this.PART_Second.ItemsSource = this.SecondButtons;
}
private void CreateItems(int itemsCount, ObservableCollection<TimeButton> list)
{
for (int i = 0; i < itemsCount; i++)
{
TimeButton timeButton = new TimeButton();
timeButton.SetValue(TimeButton.HeightProperty, this.ItemHeight);
timeButton.SetValue(TimeButton.DataContextProperty, i);
timeButton.SetValue(TimeButton.ContentProperty, (i < 10) ? "0" + i : i.ToString());
timeButton.SetValue(TimeButton.IsSelectedProperty, false);
list.Add(timeButton);
}
}
private void CreateExtraItem(ObservableCollection<TimeButton> list)
{
double height = this.ItemHeight;
if (this.Owner != null)
{
height = this.Owner.DropDownHeight;
}
else
{
height = double.IsNaN(this.Height) ? height : this.Height;
}
for (int i = 0; i < (height - this.ItemHeight) / this.ItemHeight; i++)
{
TimeButton timeButton = new TimeButton();
timeButton.SetValue(TimeButton.HeightProperty, this.ItemHeight);
timeButton.SetValue(TimeButton.IsEnabledProperty, false);
timeButton.SetValue(TimeButton.IsSelectedProperty, false);
list.Add(timeButton);
}
}
private DateTime GetDateTime(int hour, int minute, int second)
{
DateTime dt = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, hour, minute, second);
return dt;
}
/// <summary>
/// 设置选中的时间
/// </summary>
private void SetSelectedTime()
{
DateTime dt = this.GetDateTime(this.Hour, this.Minute, this.Second);
this.SelectedTime = dt;
}
#endregion
}
public class ScrollViewerBehavior
{
public static DependencyProperty VerticalOffsetProperty =
DependencyProperty.RegisterAttached("VerticalOffset",
typeof(double),
typeof(ScrollViewerBehavior),
new UIPropertyMetadata(0.0, OnVerticalOffsetChanged));
public static void SetVerticalOffset(FrameworkElement target, double value)
{
target.SetValue(VerticalOffsetProperty, value);
}
public static double GetVerticalOffset(FrameworkElement target)
{
return (double)target.GetValue(VerticalOffsetProperty);
}
private static void OnVerticalOffsetChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
{
ScrollViewer scrollViewer = target as ScrollViewer;
if (scrollViewer != null)
{
scrollViewer.ScrollToVerticalOffset((double)e.NewValue);
}
}
}
}