All the controls missing in WPF. Over 1 million downloads.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

351 lines
12 KiB

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Collections;
using System.Globalization;
namespace Microsoft.Windows.Controls
{
public class TimePicker : Control
{
#region Members
ListBox _timeListBox;
private DateTimeFormatInfo DateTimeFormatInfo { get; set; }
internal static readonly TimeSpan EndTimeDefaultValue = new TimeSpan(23, 59, 0);
internal static readonly TimeSpan StartTimeDefaultValue = new TimeSpan(0, 0, 0);
internal static readonly TimeSpan TimeIntervalDefaultValue = new TimeSpan(1, 0, 0);
#endregion //Members
#region Properties
#region EndTime
public static readonly DependencyProperty EndTimeProperty = DependencyProperty.Register("EndTime", typeof(TimeSpan), typeof(TimePicker), new UIPropertyMetadata(EndTimeDefaultValue, new PropertyChangedCallback(OnEndTimeChanged), new CoerceValueCallback(OnCoerceEndTime)));
private static object OnCoerceEndTime(DependencyObject o, object value)
{
TimePicker timePicker = o as TimePicker;
if (timePicker != null)
return timePicker.OnCoerceEndTime((TimeSpan)value);
else
return value;
}
private static void OnEndTimeChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
TimePicker timePicker = o as TimePicker;
if (timePicker != null)
timePicker.OnEndTimeChanged((TimeSpan)e.OldValue, (TimeSpan)e.NewValue);
}
protected virtual TimeSpan OnCoerceEndTime(TimeSpan value)
{
// TODO: Keep the proposed value within the desired range.
return value;
}
protected virtual void OnEndTimeChanged(TimeSpan oldValue, TimeSpan newValue)
{
// TODO: Add your property changed side-effects. Descendants can override as well.
}
public TimeSpan EndTime
{
// IMPORTANT: To maintain parity between setting a property in XAML and procedural code, do not touch the getter and setter inside this dependency property!
get
{
return (TimeSpan)GetValue(EndTimeProperty);
}
set
{
SetValue(EndTimeProperty, value);
}
}
#endregion //EndTime
#region Format
public static readonly DependencyProperty FormatProperty = DependencyProperty.Register("Format", typeof(TimeFormat), typeof(TimePicker), new UIPropertyMetadata(TimeFormat.ShortTime, OnFormatChanged));
public TimeFormat Format
{
get { return (TimeFormat)GetValue(FormatProperty); }
set { SetValue(FormatProperty, value); }
}
private static void OnFormatChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
TimePicker timePicker = o as TimePicker;
if (timePicker != null)
timePicker.OnFormatChanged((TimeFormat)e.OldValue, (TimeFormat)e.NewValue);
}
protected virtual void OnFormatChanged(TimeFormat oldValue, TimeFormat newValue)
{
}
#endregion //Format
#region FormatString
public static readonly DependencyProperty FormatStringProperty = DependencyProperty.Register("FormatString", typeof(string), typeof(TimePicker), new UIPropertyMetadata(default(String), OnFormatStringChanged));
public string FormatString
{
get { return (string)GetValue(FormatStringProperty); }
set { SetValue(FormatStringProperty, value); }
}
private static void OnFormatStringChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
TimePicker timePicker = o as TimePicker;
if (timePicker != null)
timePicker.OnFormatStringChanged((string)e.OldValue, (string)e.NewValue);
}
protected virtual void OnFormatStringChanged(string oldValue, string newValue)
{
if (string.IsNullOrEmpty(newValue))
throw new ArgumentException("CustomFormat should be specified.", FormatString);
}
#endregion //FormatString
#region IsOpen
public static readonly DependencyProperty IsOpenProperty = DependencyProperty.Register("IsOpen", typeof(bool), typeof(TimePicker), new UIPropertyMetadata(false));
public bool IsOpen
{
get { return (bool)GetValue(IsOpenProperty); }
set { SetValue(IsOpenProperty, value); }
}
#endregion //IsOpen
#region Maximum
#endregion //Maximum
#region Minimum
#endregion //Minimum
#region StartTime
public static readonly DependencyProperty StartTimeProperty = DependencyProperty.Register("StartTime", typeof(TimeSpan), typeof(TimePicker), new UIPropertyMetadata(StartTimeDefaultValue, new PropertyChangedCallback(OnStartTimeChanged), new CoerceValueCallback(OnCoerceStartTime)));
private static object OnCoerceStartTime(DependencyObject o, object value)
{
TimePicker timePicker = o as TimePicker;
if (timePicker != null)
return timePicker.OnCoerceStartTime((TimeSpan)value);
else
return value;
}
private static void OnStartTimeChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
TimePicker timePicker = o as TimePicker;
if (timePicker != null)
timePicker.OnStartTimeChanged((TimeSpan)e.OldValue, (TimeSpan)e.NewValue);
}
protected virtual TimeSpan OnCoerceStartTime(TimeSpan value)
{
// TODO: Keep the proposed value within the desired range.
return value;
}
protected virtual void OnStartTimeChanged(TimeSpan oldValue, TimeSpan newValue)
{
// TODO: Add your property changed side-effects. Descendants can override as well.
}
public TimeSpan StartTime
{
// IMPORTANT: To maintain parity between setting a property in XAML and procedural code, do not touch the getter and setter inside this dependency property!
get
{
return (TimeSpan)GetValue(StartTimeProperty);
}
set
{
SetValue(StartTimeProperty, value);
}
}
#endregion //StartTime
#region TimeInterval
public static readonly DependencyProperty TimeIntervalProperty = DependencyProperty.Register("TimeInterval", typeof(TimeSpan), typeof(TimePicker), new UIPropertyMetadata(TimeIntervalDefaultValue, OnTimeIntervalChanged));
public TimeSpan TimeInterval
{
get { return (TimeSpan)GetValue(TimeIntervalProperty); }
set { SetValue(TimeIntervalProperty, value); }
}
private static void OnTimeIntervalChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
TimePicker timePicker = o as TimePicker;
if (timePicker != null)
timePicker.OnTimeIntervalChanged((TimeSpan)e.OldValue, (TimeSpan)e.NewValue);
}
protected virtual void OnTimeIntervalChanged(TimeSpan oldValue, TimeSpan newValue)
{
// TODO: Add your property changed side-effects. Descendants can override as well.
}
#endregion //TimeInterval
#region Value
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(DateTime?), typeof(TimePicker), new UIPropertyMetadata(null, OnValueChanged));
public DateTime? Value
{
get { return (DateTime?)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
private static void OnValueChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
TimePicker timePicker = o as TimePicker;
if (timePicker != null)
timePicker.OnValueChanged((DateTime?)e.OldValue, (DateTime?)e.NewValue);
}
protected virtual void OnValueChanged(DateTime? oldValue, DateTime? newValue)
{
// TODO: Add your property changed side-effects. Descendants can override as well.
}
#endregion //Value
#endregion //Properties
#region Constructors
static TimePicker()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(TimePicker), new FrameworkPropertyMetadata(typeof(TimePicker)));
}
public TimePicker()
{
DateTimeFormatInfo = DateTimeFormatInfo.GetInstance(CultureInfo.CurrentCulture);
Keyboard.AddKeyDownHandler(this, OnKeyDown);
Mouse.AddPreviewMouseDownOutsideCapturedElementHandler(this, OnMouseDownOutsideCapturedElement);
}
#endregion //Constructors
#region Base Class Overrides
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
_timeListBox = (ListBox)GetTemplateChild("PART_TimeListItems");
_timeListBox.ItemsSource = GenerateTimeListItemsSource();
_timeListBox.SelectionChanged += TimeListBox_SelectionChanged;
}
#endregion //Base Class Overrides
#region Event Handlers
private void OnKeyDown(object sender, KeyEventArgs e)
{
switch (e.Key)
{
case Key.Escape:
case Key.Tab:
{
CloseTimePicker();
break;
}
}
}
private void OnMouseDownOutsideCapturedElement(object sender, MouseButtonEventArgs e)
{
CloseTimePicker();
}
void TimeListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.AddedItems.Count > 0)
{
TimeItem selectedTimeListItem = (TimeItem)e.AddedItems[0];
var time = selectedTimeListItem.Time; ;
var date = Value ?? DateTime.MinValue;
Value = new DateTime(date.Year, date.Month, date.Day, time.Hours, time.Minutes, time.Seconds, time.Milliseconds);
}
CloseTimePicker();
}
#endregion //Event Handlers
#region Methods
private void CloseTimePicker()
{
if (IsOpen)
IsOpen = false;
ReleaseMouseCapture();
}
public IEnumerable GenerateTimeListItemsSource()
{
TimeSpan time = StartTime;
TimeSpan endTime = EndTime;
if (endTime <= time)
{
endTime = EndTimeDefaultValue;
time = StartTimeDefaultValue;
}
TimeSpan timeInterval = TimeInterval;
if (time != null && endTime != null && timeInterval != null && timeInterval.Ticks > 0)
{
while (time <= endTime)
{
yield return new TimeItem(DateTime.MinValue.Add(time).ToString(GetTimeFormat(), CultureInfo.CurrentCulture), time);
time = time.Add(timeInterval);
}
yield break;
}
}
private string GetTimeFormat()
{
switch (Format)
{
case TimeFormat.Custom:
return FormatString;
case TimeFormat.LongTime:
return DateTimeFormatInfo.LongTimePattern;
case TimeFormat.ShortTime:
return DateTimeFormatInfo.ShortTimePattern;
default:
return DateTimeFormatInfo.ShortTimePattern;
}
}
#endregion //Methods
}
}