6 changed files with 406 additions and 0 deletions
@ -0,0 +1,33 @@ |
|||
using System; |
|||
using System.Windows.Data; |
|||
|
|||
namespace Microsoft.Windows.Controls.Core.Converters |
|||
{ |
|||
public class TimeFormatToDateTimeFormatConverter : IValueConverter |
|||
{ |
|||
#region IValueConverter Members
|
|||
|
|||
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) |
|||
{ |
|||
TimeFormat timeFormat = (TimeFormat)value; |
|||
switch (timeFormat) |
|||
{ |
|||
case TimeFormat.Custom: |
|||
return DateTimeFormat.Custom; |
|||
case TimeFormat.ShortTime: |
|||
return DateTimeFormat.ShortTime; |
|||
case TimeFormat.LongTime: |
|||
return DateTimeFormat.LongTime; |
|||
default: |
|||
return DateTimeFormat.ShortTime; |
|||
} |
|||
} |
|||
|
|||
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
|
|||
#endregion
|
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
|
|||
namespace Microsoft.Windows.Controls |
|||
{ |
|||
public enum TimeFormat |
|||
{ |
|||
Custom, |
|||
ShortTime, |
|||
LongTime |
|||
} |
|||
} |
|||
@ -0,0 +1,262 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Windows; |
|||
using System.Windows.Controls; |
|||
using System.Windows.Data; |
|||
using System.Windows.Documents; |
|||
using System.Windows.Input; |
|||
using System.Windows.Media; |
|||
using System.Windows.Media.Imaging; |
|||
using System.Windows.Navigation; |
|||
using System.Windows.Shapes; |
|||
using System.Collections; |
|||
|
|||
namespace Microsoft.Windows.Controls |
|||
{ |
|||
public class TimePicker : Control |
|||
{ |
|||
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); |
|||
|
|||
#region Members
|
|||
|
|||
ListBox _timeListBox; |
|||
|
|||
#endregion //Members
|
|||
|
|||
#region Properties
|
|||
|
|||
#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 SelectedDate
|
|||
|
|||
public static readonly DependencyProperty SelectedDateProperty = DependencyProperty.Register("SelectedDate", typeof(DateTime?), typeof(TimePicker), new UIPropertyMetadata(DateTime.Now, OnSelectedDateChanged)); |
|||
public DateTime? SelectedDate |
|||
{ |
|||
get { return (DateTime?)GetValue(SelectedDateProperty); } |
|||
set { SetValue(SelectedDateProperty, value); } |
|||
} |
|||
|
|||
private static void OnSelectedDateChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) |
|||
{ |
|||
TimePicker timePicker = o as TimePicker; |
|||
if (timePicker != null) |
|||
timePicker.OnSelectedDateChanged((DateTime?)e.OldValue, (DateTime?)e.NewValue); |
|||
} |
|||
|
|||
protected virtual void OnSelectedDateChanged(DateTime? oldValue, DateTime? newValue) |
|||
{ |
|||
|
|||
} |
|||
|
|||
#endregion //SelectedDate
|
|||
|
|||
#region SelectedTime
|
|||
|
|||
public static readonly DependencyProperty SelectedTimeProperty = DependencyProperty.Register("SelectedTime", typeof(TimeSpan?), typeof(TimePicker), new UIPropertyMetadata(null, OnSelectedTimeChanged)); |
|||
public TimeSpan? SelectedTime |
|||
{ |
|||
get { return (TimeSpan?)GetValue(SelectedTimeProperty); } |
|||
set { SetValue(SelectedTimeProperty, value); } |
|||
} |
|||
|
|||
private static void OnSelectedTimeChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) |
|||
{ |
|||
TimePicker timePicker = o as TimePicker; |
|||
if (timePicker != null) |
|||
timePicker.OnSelectedTimeChanged((TimeSpan?)e.OldValue, (TimeSpan?)e.NewValue); |
|||
} |
|||
|
|||
protected virtual void OnSelectedTimeChanged(TimeSpan? oldValue, TimeSpan? newValue) |
|||
{ |
|||
var current = DateTime.Now; |
|||
|
|||
var date = SelectedDate ?? current; |
|||
var time = SelectedTime ?? current.TimeOfDay; |
|||
|
|||
SelectedDate = new DateTime(date.Year, date.Month, date.Day, time.Hours, time.Minutes, time.Seconds, time.Milliseconds); |
|||
} |
|||
|
|||
#endregion //SelectedTime
|
|||
|
|||
#endregion //Properties
|
|||
|
|||
#region Constructors
|
|||
|
|||
static TimePicker() |
|||
{ |
|||
DefaultStyleKeyProperty.OverrideMetadata(typeof(TimePicker), new FrameworkPropertyMetadata(typeof(TimePicker))); |
|||
} |
|||
|
|||
public TimePicker() |
|||
{ |
|||
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 = GenerateItemsSource(); |
|||
_timeListBox.SelectionChanged += new SelectionChangedEventHandler(_timeListBox_SelectionChanged); |
|||
} |
|||
|
|||
void _timeListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) |
|||
{ |
|||
//if (e.AddedItems.Count > 0)
|
|||
//{
|
|||
// TimeSpan newTime = (TimeSpan)e.AddedItems[0];
|
|||
|
|||
// var current = DateTime.Now;
|
|||
|
|||
// var date = this.SelectedDate.HasValue ? this.SelectedDate.Value : current;
|
|||
// var time = this.SelectedTime.HasValue ? this.SelectedTime.Value : current.TimeOfDay;
|
|||
|
|||
// SelectedDate = new DateTime(date.Year, date.Month, date.Day, time.Hours, time.Minutes, time.Seconds, time.Milliseconds);
|
|||
//}
|
|||
|
|||
CloseTimePicker(); |
|||
} |
|||
|
|||
#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(); |
|||
} |
|||
|
|||
#endregion //Event Handlers
|
|||
|
|||
#region Methods
|
|||
|
|||
private void CloseTimePicker() |
|||
{ |
|||
if (IsOpen) |
|||
IsOpen = false; |
|||
ReleaseMouseCapture(); |
|||
} |
|||
|
|||
private static IEnumerable GenerateItemsSource() |
|||
{ |
|||
//TimeSpan time = this.StartTime;
|
|||
//TimeSpan endTime = this.EndTime;
|
|||
|
|||
TimeSpan time = StartTimeDefaultValue; |
|||
TimeSpan endTime = EndTimeDefaultValue; |
|||
|
|||
if (endTime <= time) |
|||
{ |
|||
endTime = EndTimeDefaultValue; |
|||
time = StartTimeDefaultValue; |
|||
} |
|||
|
|||
//TimeSpan timeInterval = this.TimeInterval;
|
|||
TimeSpan timeInterval = TimeIntervalDefaultValue; |
|||
|
|||
if (time != null && endTime != null && timeInterval != null && timeInterval.Ticks > 0) |
|||
{ |
|||
while (time <= endTime) |
|||
{ |
|||
yield return time; |
|||
time = time.Add(timeInterval); |
|||
} |
|||
yield break; |
|||
} |
|||
|
|||
} |
|||
|
|||
#endregion //Methods
|
|||
} |
|||
} |
|||
@ -0,0 +1,93 @@ |
|||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
xmlns:local="clr-namespace:Microsoft.Windows.Controls" |
|||
xmlns:chrome="clr-namespace:Microsoft.Windows.Controls.Chromes" |
|||
xmlns:coreConverters="clr-namespace:Microsoft.Windows.Controls.Core.Converters"> |
|||
|
|||
<coreConverters:InverseBoolConverter x:Key="InverseBoolConverter" /> |
|||
<coreConverters:TimeFormatToDateTimeFormatConverter x:Key="TimeFormatToDateTimeFormatConverter" /> |
|||
|
|||
<LinearGradientBrush x:Key="PopupDarkBorderBrush" EndPoint="0.5,1" StartPoint="0.5,0"> |
|||
<GradientStop Color="#FFA3AEB9" Offset="0"/> |
|||
<GradientStop Color="#FF8399A9" Offset="0.375"/> |
|||
<GradientStop Color="#FF718597" Offset="0.375"/> |
|||
<GradientStop Color="#FF617584" Offset="1"/> |
|||
</LinearGradientBrush> |
|||
|
|||
<LinearGradientBrush x:Key="PopupBackgroundBrush" StartPoint="0,0" EndPoint="0,1"> |
|||
<LinearGradientBrush.GradientStops> |
|||
<GradientStopCollection> |
|||
<GradientStop Offset="0" Color="#FFffffff"/> |
|||
<GradientStop Offset="1" Color="#FFE8EBED"/> |
|||
</GradientStopCollection> |
|||
</LinearGradientBrush.GradientStops> |
|||
</LinearGradientBrush> |
|||
|
|||
<Style x:Key="TimePickerToggleButtonStyle" TargetType="ToggleButton"> |
|||
<Setter Property="Template"> |
|||
<Setter.Value> |
|||
<ControlTemplate TargetType="ToggleButton"> |
|||
<Grid SnapsToDevicePixels="True"> |
|||
<chrome:ButtonChrome x:Name="ToggleButtonChrome" |
|||
CornerRadius="0,2.75,2.75,0" |
|||
RenderMouseOver="{TemplateBinding IsMouseOver}" |
|||
RenderPressed="{TemplateBinding IsPressed}" /> |
|||
|
|||
<Grid> |
|||
<Grid.ColumnDefinitions> |
|||
<ColumnDefinition Width="*"/> |
|||
<ColumnDefinition Width="Auto"/> |
|||
</Grid.ColumnDefinitions> |
|||
|
|||
<ContentPresenter HorizontalAlignment="Stretch" VerticalAlignment="Stretch" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" /> |
|||
|
|||
<Grid x:Name="arrowGlyph" IsHitTestVisible="False" Grid.Column="1" Margin="5"> |
|||
<Path Width="7" Height="4" Data="M 0,1 C0,1 0,0 0,0 0,0 3,0 3,0 3,0 3,1 3,1 3,1 4,1 4,1 4,1 4,0 4,0 4,0 7,0 7,0 7,0 7,1 7,1 7,1 6,1 6,1 6,1 6,2 6,2 6,2 5,2 5,2 5,2 5,3 5,3 5,3 4,3 4,3 4,3 4,4 4,4 4,4 3,4 3,4 3,4 3,3 3,3 3,3 2,3 2,3 2,3 2,2 2,2 2,2 1,2 1,2 1,2 1,1 1,1 1,1 0,1 0,1 z" Fill="#FF000000"/> |
|||
</Grid> |
|||
</Grid> |
|||
</Grid> |
|||
</ControlTemplate> |
|||
</Setter.Value> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
<!-- =============================================================================== --> |
|||
<!-- TimePicker --> |
|||
<!-- =============================================================================== --> |
|||
|
|||
<Style TargetType="{x:Type local:TimePicker}"> |
|||
<Setter Property="Template"> |
|||
<Setter.Value> |
|||
<ControlTemplate TargetType="{x:Type local:TimePicker}"> |
|||
<Border> |
|||
<Grid> |
|||
<Grid> |
|||
<Grid.ColumnDefinitions> |
|||
<ColumnDefinition Width="*" /> |
|||
<ColumnDefinition Width="Auto" /> |
|||
</Grid.ColumnDefinitions> |
|||
<local:DateTimeUpDown x:Name="PART_TimeUpDown" BorderThickness="1,1,0,1" |
|||
Format="{TemplateBinding Format, Converter={StaticResource TimeFormatToDateTimeFormatConverter}}" |
|||
FormatString="{TemplateBinding FormatString}" |
|||
Value="{Binding SelectedDate, RelativeSource={RelativeSource TemplatedParent}}" /> |
|||
<ToggleButton x:Name="_timePickerToggleButton" Grid.Column="1" |
|||
IsChecked="{Binding IsOpen, RelativeSource={RelativeSource TemplatedParent}}" |
|||
Style="{StaticResource TimePickerToggleButtonStyle}" |
|||
IsHitTestVisible="{Binding IsOpen, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource InverseBoolConverter}}"/> |
|||
</Grid> |
|||
<Popup IsOpen="{Binding IsChecked, ElementName=_timePickerToggleButton}" StaysOpen="False"> |
|||
<Border BorderThickness="1" Background="{StaticResource PopupBackgroundBrush}" BorderBrush="{StaticResource PopupDarkBorderBrush}" > |
|||
<ListBox x:Name="PART_TimeListItems" BorderThickness="0" |
|||
SelectedItem="{Binding SelectedTime, RelativeSource={RelativeSource TemplatedParent}}"> |
|||
|
|||
</ListBox> |
|||
</Border> |
|||
</Popup> |
|||
</Grid> |
|||
</Border> |
|||
</ControlTemplate> |
|||
</Setter.Value> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
</ResourceDictionary> |
|||
Loading…
Reference in new issue