Init
This commit is contained in:
@@ -0,0 +1,472 @@
|
||||
/*************************************************************************************
|
||||
|
||||
Extended WPF Toolkit
|
||||
|
||||
Copyright (C) 2007-2013 Xceed Software Inc.
|
||||
|
||||
This program is provided to you under the terms of the Microsoft Public
|
||||
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
|
||||
|
||||
For more features, controls, and fast professional support,
|
||||
pick up the Plus Edition at http://xceed.com/wpf_toolkit
|
||||
|
||||
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
|
||||
|
||||
***********************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using Xceed.Wpf.Toolkit.Core.Utilities;
|
||||
using Xceed.Wpf.Toolkit.Primitives;
|
||||
#if VS2008
|
||||
using Microsoft.Windows.Controls;
|
||||
using Microsoft.Windows.Controls.Primitives;
|
||||
#endif
|
||||
|
||||
namespace Xceed.Wpf.Toolkit
|
||||
{
|
||||
[TemplatePart( Name = PART_Calendar, Type = typeof( Calendar ) )]
|
||||
[TemplatePart( Name = PART_TimeUpDown, Type = typeof( TimePicker ) )]
|
||||
public class DateTimePicker : DateTimePickerBase
|
||||
{
|
||||
private const string PART_Calendar = "PART_Calendar";
|
||||
private const string PART_TimeUpDown = "PART_TimeUpDown";
|
||||
|
||||
#region Members
|
||||
|
||||
private Calendar _calendar;
|
||||
private TimePicker _timePicker;
|
||||
private DateTime? _calendarTemporaryDateTime;
|
||||
private DateTime? _calendarIntendedDateTime;
|
||||
|
||||
#endregion //Members
|
||||
|
||||
#region Properties
|
||||
|
||||
#region AutoCloseCalendar
|
||||
|
||||
public static readonly DependencyProperty AutoCloseCalendarProperty = DependencyProperty.Register( "AutoCloseCalendar", typeof( bool ), typeof( DateTimePicker ), new UIPropertyMetadata( false ) );
|
||||
public bool AutoCloseCalendar
|
||||
{
|
||||
get
|
||||
{
|
||||
return ( bool )GetValue( AutoCloseCalendarProperty );
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue( AutoCloseCalendarProperty, value );
|
||||
}
|
||||
}
|
||||
|
||||
#endregion //AutoCloseCalendar
|
||||
|
||||
#region CalendarDisplayMode
|
||||
|
||||
public static readonly DependencyProperty CalendarDisplayModeProperty = DependencyProperty.Register( "CalendarDisplayMode", typeof( CalendarMode )
|
||||
, typeof( DateTimePicker ), new UIPropertyMetadata( CalendarMode.Month ) );
|
||||
public CalendarMode CalendarDisplayMode
|
||||
{
|
||||
get
|
||||
{
|
||||
return (CalendarMode)GetValue( CalendarDisplayModeProperty );
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue( CalendarDisplayModeProperty, value );
|
||||
}
|
||||
}
|
||||
|
||||
#endregion //CalendarDisplayMode
|
||||
|
||||
#region CalendarWidth
|
||||
|
||||
public static readonly DependencyProperty CalendarWidthProperty = DependencyProperty.Register( "CalendarWidth", typeof( double )
|
||||
, typeof( DateTimePicker ), new UIPropertyMetadata( 178d ) );
|
||||
public double CalendarWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
return ( double )GetValue( CalendarWidthProperty );
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue( CalendarWidthProperty, value );
|
||||
}
|
||||
}
|
||||
|
||||
#endregion //CalendarWidth
|
||||
|
||||
#region TimeFormat
|
||||
|
||||
public static readonly DependencyProperty TimeFormatProperty = DependencyProperty.Register( "TimeFormat", typeof( DateTimeFormat ), typeof( DateTimePicker ), new UIPropertyMetadata( DateTimeFormat.ShortTime ) );
|
||||
public DateTimeFormat TimeFormat
|
||||
{
|
||||
get
|
||||
{
|
||||
return ( DateTimeFormat )GetValue( TimeFormatProperty );
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue( TimeFormatProperty, value );
|
||||
}
|
||||
}
|
||||
|
||||
#endregion //TimeFormat
|
||||
|
||||
#region TimeFormatString
|
||||
|
||||
public static readonly DependencyProperty TimeFormatStringProperty = DependencyProperty.Register( "TimeFormatString", typeof( string ), typeof( DateTimePicker ), new UIPropertyMetadata( default( String ) ), IsTimeFormatStringValid );
|
||||
public string TimeFormatString
|
||||
{
|
||||
get
|
||||
{
|
||||
return ( string )GetValue( TimeFormatStringProperty );
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue( TimeFormatStringProperty, value );
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsTimeFormatStringValid(object value)
|
||||
{
|
||||
return DateTimeUpDown.IsFormatStringValid( value );
|
||||
}
|
||||
|
||||
#endregion //TimeFormatString
|
||||
|
||||
#region TimePickerAllowSpin
|
||||
|
||||
public static readonly DependencyProperty TimePickerAllowSpinProperty = DependencyProperty.Register( "TimePickerAllowSpin", typeof( bool ), typeof( DateTimePicker ), new UIPropertyMetadata( true ) );
|
||||
public bool TimePickerAllowSpin
|
||||
{
|
||||
get
|
||||
{
|
||||
return (bool)GetValue( TimePickerAllowSpinProperty );
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue( TimePickerAllowSpinProperty, value );
|
||||
}
|
||||
}
|
||||
|
||||
#endregion //TimePickerAllowSpin
|
||||
|
||||
#region TimePickerShowButtonSpinner
|
||||
|
||||
public static readonly DependencyProperty TimePickerShowButtonSpinnerProperty = DependencyProperty.Register( "TimePickerShowButtonSpinner", typeof( bool ), typeof( DateTimePicker ), new UIPropertyMetadata( true ) );
|
||||
public bool TimePickerShowButtonSpinner
|
||||
{
|
||||
get
|
||||
{
|
||||
return (bool)GetValue( TimePickerShowButtonSpinnerProperty );
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue( TimePickerShowButtonSpinnerProperty, value );
|
||||
}
|
||||
}
|
||||
|
||||
#endregion //TimePickerShowButtonSpinner
|
||||
|
||||
#region TimePickerVisibility
|
||||
|
||||
public static readonly DependencyProperty TimePickerVisibilityProperty = DependencyProperty.Register( "TimePickerVisibility", typeof( Visibility ), typeof( DateTimePicker ), new UIPropertyMetadata( Visibility.Visible ) );
|
||||
public Visibility TimePickerVisibility
|
||||
{
|
||||
get
|
||||
{
|
||||
return ( Visibility )GetValue( TimePickerVisibilityProperty );
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue( TimePickerVisibilityProperty, value );
|
||||
}
|
||||
}
|
||||
|
||||
#endregion //TimePickerVisibility
|
||||
|
||||
#region TimeWatermark
|
||||
|
||||
public static readonly DependencyProperty TimeWatermarkProperty = DependencyProperty.Register( "TimeWatermark", typeof( object ), typeof( DateTimePicker ), new UIPropertyMetadata( null ) );
|
||||
public object TimeWatermark
|
||||
{
|
||||
get
|
||||
{
|
||||
return ( object )GetValue( TimeWatermarkProperty );
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue( TimeWatermarkProperty, value );
|
||||
}
|
||||
}
|
||||
|
||||
#endregion //TimeWatermark
|
||||
|
||||
#region TimeWatermarkTemplate
|
||||
|
||||
public static readonly DependencyProperty TimeWatermarkTemplateProperty = DependencyProperty.Register( "TimeWatermarkTemplate", typeof( DataTemplate ), typeof( DateTimePicker ), new UIPropertyMetadata( null ) );
|
||||
public DataTemplate TimeWatermarkTemplate
|
||||
{
|
||||
get
|
||||
{
|
||||
return ( DataTemplate )GetValue( TimeWatermarkTemplateProperty );
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue( TimeWatermarkTemplateProperty, value );
|
||||
}
|
||||
}
|
||||
|
||||
#endregion //TimeWatermarkTemplate
|
||||
|
||||
#endregion //Properties
|
||||
|
||||
#region Constructors
|
||||
|
||||
static DateTimePicker()
|
||||
{
|
||||
DefaultStyleKeyProperty.OverrideMetadata( typeof( DateTimePicker ), new FrameworkPropertyMetadata( typeof( DateTimePicker ) ) );
|
||||
UpdateValueOnEnterKeyProperty.OverrideMetadata( typeof( DateTimePicker ), new FrameworkPropertyMetadata( true ) );
|
||||
}
|
||||
|
||||
public DateTimePicker()
|
||||
{
|
||||
}
|
||||
|
||||
#endregion //Constructors
|
||||
|
||||
#region Base Class Overrides
|
||||
|
||||
public override void OnApplyTemplate()
|
||||
{
|
||||
base.OnApplyTemplate();
|
||||
|
||||
if( _calendar != null )
|
||||
_calendar.SelectedDatesChanged -= Calendar_SelectedDatesChanged;
|
||||
|
||||
_calendar = GetTemplateChild( PART_Calendar ) as Calendar;
|
||||
|
||||
if( _calendar != null )
|
||||
{
|
||||
_calendar.SelectedDatesChanged += Calendar_SelectedDatesChanged;
|
||||
_calendar.SelectedDate = Value ?? null;
|
||||
_calendar.DisplayDate = Value ?? this.ContextNow;
|
||||
this.SetBlackOutDates();
|
||||
}
|
||||
|
||||
if( _timePicker != null )
|
||||
{
|
||||
_timePicker.ValueChanged -= this.TimePicker_ValueChanged;
|
||||
}
|
||||
_timePicker = GetTemplateChild( PART_TimeUpDown ) as TimePicker;
|
||||
if( _timePicker != null )
|
||||
{
|
||||
_timePicker.ValueChanged += this.TimePicker_ValueChanged;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPreviewMouseUp( MouseButtonEventArgs e )
|
||||
{
|
||||
if( Mouse.Captured is CalendarItem)
|
||||
{
|
||||
Mouse.Capture( null );
|
||||
|
||||
if( AutoCloseCalendar && ( _calendar.DisplayMode == CalendarMode.Month ) )
|
||||
{
|
||||
ClosePopup( true );
|
||||
}
|
||||
}
|
||||
base.OnPreviewMouseUp( e );
|
||||
}
|
||||
|
||||
protected override void OnValueChanged( DateTime? oldValue, DateTime? newValue )
|
||||
{
|
||||
//The calendar only select the Date part, not the time part.
|
||||
DateTime? newValueDate = (newValue != null)
|
||||
? newValue.Value.Date
|
||||
: (DateTime?)null;
|
||||
|
||||
if( _calendar != null && _calendar.SelectedDate != newValueDate)
|
||||
{
|
||||
_calendar.SelectedDate = newValueDate;
|
||||
_calendar.DisplayDate = newValue.GetValueOrDefault( this.ContextNow );
|
||||
}
|
||||
|
||||
//If we change any part of the datetime without
|
||||
//using the calendar when the actual date is temporary,
|
||||
//clear the temporary value.
|
||||
if( _calendarTemporaryDateTime != null &&
|
||||
newValue != _calendarTemporaryDateTime )
|
||||
{
|
||||
_calendarTemporaryDateTime = null;
|
||||
_calendarIntendedDateTime = null;
|
||||
}
|
||||
|
||||
base.OnValueChanged( oldValue, newValue );
|
||||
}
|
||||
|
||||
protected override void OnIsOpenChanged( bool oldValue, bool newValue )
|
||||
{
|
||||
base.OnIsOpenChanged( oldValue, newValue );
|
||||
|
||||
if( !newValue )
|
||||
{
|
||||
_calendarTemporaryDateTime = null;
|
||||
_calendarIntendedDateTime = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPreviewKeyDown( KeyEventArgs e )
|
||||
{
|
||||
//if the calendar is open then we don't want to modify the behavior of navigating the calendar control with the Up/Down keys.
|
||||
if( !IsOpen )
|
||||
base.OnPreviewKeyDown( e );
|
||||
}
|
||||
|
||||
protected override void OnMaximumChanged( DateTime? oldValue, DateTime? newValue )
|
||||
{
|
||||
base.OnMaximumChanged( oldValue, newValue );
|
||||
|
||||
this.SetBlackOutDates();
|
||||
}
|
||||
|
||||
protected override void OnMinimumChanged( DateTime? oldValue, DateTime? newValue )
|
||||
{
|
||||
base.OnMinimumChanged( oldValue, newValue );
|
||||
|
||||
this.SetBlackOutDates();
|
||||
}
|
||||
|
||||
#endregion //Base Class Overrides
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
protected override void HandleKeyDown( object sender, KeyEventArgs e )
|
||||
{
|
||||
// The base call will handle the Ctrl+Down, Enter and Esc keys
|
||||
// in order to open o r close the popup.
|
||||
//Do not close the Calendar if the call is handled
|
||||
//by the TimePicker inside the DateTimePicker template
|
||||
if( IsOpen
|
||||
&& _timePicker.IsKeyboardFocusWithin
|
||||
&& ( _timePicker.IsOpen || e.Handled ) )
|
||||
return;
|
||||
|
||||
base.HandleKeyDown( sender, e );
|
||||
}
|
||||
|
||||
private void TimePicker_ValueChanged( object sender, RoutedPropertyChangedEventArgs<object> e )
|
||||
{
|
||||
e.Handled = true;
|
||||
|
||||
// if UpdateValueOnEnterKey is true,
|
||||
// Sync Value on Text only when Enter Key is pressed.
|
||||
if( this.UpdateValueOnEnterKey )
|
||||
{
|
||||
var newTime = e.NewValue as DateTime?;
|
||||
if( newTime != null )
|
||||
{
|
||||
_fireSelectionChangedEvent = false;
|
||||
var currentDate = this.ConvertTextToValue( this.TextBox.Text );
|
||||
var date = currentDate ?? this.ContextNow;
|
||||
var newValue = new DateTime( date.Year, date.Month, date.Day, newTime.Value.Hour, newTime.Value.Minute, newTime.Value.Second, newTime.Value.Millisecond, date.Kind );
|
||||
this.TextBox.Text = newValue.ToString( this.GetFormatString( this.Format ), this.CultureInfo );
|
||||
_fireSelectionChangedEvent = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Calendar_SelectedDatesChanged( object sender, SelectionChangedEventArgs e )
|
||||
{
|
||||
if( e.AddedItems.Count > 0 )
|
||||
{
|
||||
var newDate = ( DateTime? )e.AddedItems[ 0 ];
|
||||
|
||||
if( newDate != null )
|
||||
{
|
||||
//The Calendar will always return a date with an "Unspecified" Kind.
|
||||
//Force the expected kind to the value.
|
||||
newDate = DateTime.SpecifyKind( newDate.Value, this.Kind );
|
||||
|
||||
// Only change the year, month, and day part of the value. Keep everything to the last "tick."
|
||||
// "Milliseconds" aren't precise enough. Use a mathematical scheme instead.
|
||||
if( _calendarIntendedDateTime != null )
|
||||
{
|
||||
newDate = newDate.Value.Date + _calendarIntendedDateTime.Value.TimeOfDay;
|
||||
_calendarTemporaryDateTime = null;
|
||||
_calendarIntendedDateTime = null;
|
||||
}
|
||||
else if( Value != null )
|
||||
{
|
||||
newDate = newDate.Value.Date + Value.Value.TimeOfDay;
|
||||
}
|
||||
|
||||
// Always be sure that the time part of the selected value is always
|
||||
// within the bound of the min max. The time part could be altered
|
||||
// if the calendar's selected date match the Minimum or Maximum date.
|
||||
// Keep in memory the intended time of day, in case that the selected
|
||||
// calendar date is only transitory (browsing the calendar with the keyboard)
|
||||
var limitedDateTime = this.GetClippedMinMaxValue( newDate );
|
||||
|
||||
if( limitedDateTime.Value != newDate.Value )
|
||||
{
|
||||
_calendarTemporaryDateTime = limitedDateTime;
|
||||
_calendarIntendedDateTime = newDate;
|
||||
newDate = limitedDateTime;
|
||||
}
|
||||
}
|
||||
|
||||
if( this.UpdateValueOnEnterKey )
|
||||
{
|
||||
_fireSelectionChangedEvent = false;
|
||||
this.TextBox.Text = newDate.Value.ToString( this.GetFormatString( this.Format ), this.CultureInfo );
|
||||
_fireSelectionChangedEvent = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !object.Equals( newDate, Value ) )
|
||||
{
|
||||
this.Value = newDate;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Popup_Opened( object sender, EventArgs e )
|
||||
{
|
||||
base.Popup_Opened( sender, e );
|
||||
|
||||
if( _calendar != null )
|
||||
_calendar.Focus();
|
||||
}
|
||||
|
||||
#endregion //Event Handlers
|
||||
|
||||
#region Methods
|
||||
|
||||
private void SetBlackOutDates()
|
||||
{
|
||||
if( _calendar != null )
|
||||
{
|
||||
_calendar.BlackoutDates.Clear();
|
||||
|
||||
if( ( this.Minimum != null ) && this.Minimum.HasValue && ( this.Minimum.Value != DateTime.MinValue ) )
|
||||
{
|
||||
DateTime minDate = this.Minimum.Value;
|
||||
_calendar.BlackoutDates.Add( new CalendarDateRange( DateTime.MinValue, minDate.AddDays( -1 ) ) );
|
||||
}
|
||||
if( ( this.Maximum != null ) && this.Maximum.HasValue && ( this.Maximum.Value != DateTime.MaxValue ) )
|
||||
{
|
||||
DateTime maxDate = this.Maximum.Value;
|
||||
_calendar.BlackoutDates.Add( new CalendarDateRange( maxDate.AddDays( 1 ), DateTime.MaxValue ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion //Methods
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user