DatePicker.cs :  » 2.6.4-mono-.net-core » System.Windows » System » Windows » Controls » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » 2.6.4 mono .net core » System.Windows 
System.Windows » System » Windows » Controls » DatePicker.cs
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Windows.Automation.Peers;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;

namespace System.Windows.Controls{
    /// <summary>
    /// Represents a control that allows the user to select a date.
    /// </summary>
    [TemplatePart(Name = DatePicker.ElementRoot, Type = typeof(FrameworkElement))]
    [TemplatePart(Name = DatePicker.ElementTextBox, Type = typeof(DatePickerTextBox))]
    [TemplatePart(Name = DatePicker.ElementButton, Type = typeof(Button))]
    [TemplatePart(Name = DatePicker.ElementPopup, Type = typeof(Popup))]
    [TemplateVisualState(Name = VisualStates.StateNormal, GroupName = VisualStates.GroupCommon)]
    [TemplateVisualState(Name = VisualStates.StateDisabled, GroupName = VisualStates.GroupCommon)]
    public partial class DatePicker : Control
    {
        #region Constants

        private const string ElementRoot = "Root";
        private const string ElementTextBox = "TextBox";
        private const string ElementButton = "Button";
        private const string ElementPopup = "Popup";

        #endregion Constants

        #region Data

        private Calendar _calendar;
        private string _defaultText;
        private Button _dropDownButton;
        private Canvas _outsideCanvas;
        private Canvas _outsidePopupCanvas;
        private Popup _popUp;
        private FrameworkElement _root;
        private bool _settingSelectedDate;
        private DatePickerTextBox _textBox;

        #endregion Data

        #region Public Events

        /// <summary>
        /// Occurs when the drop-down Calendar is closed.
        /// </summary>
        public event RoutedEventHandler CalendarClosed;

        /// <summary>
        /// Occurs when the drop-down Calendar is opened.
        /// </summary>
        public event RoutedEventHandler CalendarOpened;

        /// <summary>
        /// Occurs when text entered into the DatePicker cannot be parsed or the Date is not valid to be selected.
        /// </summary>
        public event EventHandler<DatePickerDateValidationErrorEventArgs> DateValidationError;

        /// <summary>
        /// Occurs when a date is selected.
        /// </summary>
        public event EventHandler<SelectionChangedEventArgs> SelectedDateChanged;

        #endregion PublicEvents

        /// <summary>
        /// Initializes a new instance of the DatePicker class. 
        /// </summary>
        public DatePicker()
        {
            InitializeCalendar();
            this.IsEnabledChanged += new DependencyPropertyChangedEventHandler(OnIsEnabledChanged);
            this.FirstDayOfWeek = DateTimeHelper.GetCurrentDateFormat().FirstDayOfWeek;
            this.IsTodayHighlighted = true;
            this.SelectedDateFormat = DatePickerFormat.Short;
            this._defaultText = string.Empty;
            this.SetValueNoCallback(DatePicker.TextProperty, string.Empty);
            this.DisplayDate = DateTime.Today;
            this.IsDropDownOpen = false;
            this.GotFocus += new RoutedEventHandler(DatePicker_GotFocus);
            this.LostFocus += new RoutedEventHandler(DatePicker_LostFocus);
            this.BlackoutDates = this._calendar.BlackoutDates;
            DefaultStyleKey = typeof(DatePicker);
        }

        #region Public properties

        #region BlackoutDates

        /// <summary>
        /// Gets the days that are not selectable.
        /// </summary>
        public CalendarBlackoutDatesCollection BlackoutDates
        {
            get;
            private set;
        }

        #endregion BlackoutDates

        #region CalendarStyle

        /// <summary>
        /// Gets or sets the style that is used when rendering the calendar.
        /// </summary>
        public Style CalendarStyle
        {
            get { return (Style)GetValue(CalendarStyleProperty); }
            set { SetValue(CalendarStyleProperty, value); }
        }

        /// <summary>
        /// Identifies the CalendarStyle dependency property.
        /// </summary>
        public static readonly DependencyProperty CalendarStyleProperty =
            DependencyProperty.Register(
            "CalendarStyle",
            typeof(Style),
            typeof(DatePicker),
            new PropertyMetadata(OnCalendarStyleChanged));

        /// <summary>
        /// CalendarStyleProperty property changed handler.
        /// </summary>
        /// <param name="d">DatePicker that changed its CalendarStyle.</param>
        /// <param name="e">DependencyPropertyChangedEventArgs.</param>
        private static void OnCalendarStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Style newStyle = e.NewValue as Style;
            if (newStyle != null)
            {
                DatePicker datePicker = d as DatePicker;

                if (datePicker != null)
                {
                    Style oldStyle = e.OldValue as Style;

                    // Set the style for the calendar if it has not already been set

                    if (datePicker._calendar != null)
                    {
                        // 

                        if (datePicker._calendar.Style == null || datePicker._calendar.Style == oldStyle)
                        {
                            datePicker._calendar.Style = newStyle;
                        }
                    }
                }
            }
        }

        #endregion CalendarStyle

        #region DisplayDate

        /// <summary>
        /// Gets or sets the date to display.
        /// </summary>
        /// 
        [TypeConverter(typeof(DateTimeTypeConverter))]
        public DateTime DisplayDate
        {
            get { return (DateTime)GetValue(DisplayDateProperty); }
            set { SetValue(DisplayDateProperty, value); }
        }
        /// <summary>
        /// Identifies the DisplayDate dependency property.
        /// </summary>
        public static readonly DependencyProperty DisplayDateProperty =
            DependencyProperty.Register(
            "DisplayDate",
            typeof(DateTime),
            typeof(DatePicker),
            new PropertyMetadata(OnDisplayDateChanged));

        /// <summary>
        /// DisplayDateProperty property changed handler.
        /// </summary>
        /// <param name="d">DatePicker that changed its DisplayDate.</param>
        /// <param name="e">DependencyPropertyChangedEventArgs.</param>
        private static void OnDisplayDateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DatePicker datePicker = d as DatePicker;
            Debug.Assert(datePicker != null);

            if ( DateTimeHelper.CompareYearMonth(datePicker._calendar.DisplayDate,(DateTime)e.NewValue) != 0)
            {
                datePicker._calendar.DisplayDate = datePicker.DisplayDate;

                if (DateTime.Compare(datePicker._calendar.DisplayDate, datePicker.DisplayDate) != 0)
                {
                    datePicker.DisplayDate = datePicker._calendar.DisplayDate;
                }
            }
        }

        #endregion DisplayDate

        #region DisplayDateEnd

        /// <summary>
        /// Gets or sets the last date to be displayed.
        /// </summary>
        /// 
        [TypeConverter(typeof(DateTimeTypeConverter))]
        public DateTime? DisplayDateEnd
        {
            get { return (DateTime?)GetValue(DisplayDateEndProperty); }
            set { SetValue(DisplayDateEndProperty, value); }
        }

        /// <summary>
        /// Identifies the DisplayDateEnd dependency property.
        /// </summary>
        public static readonly DependencyProperty DisplayDateEndProperty =
            DependencyProperty.Register(
            "DisplayDateEnd",
            typeof(DateTime?),
            typeof(DatePicker),
            new PropertyMetadata(OnDisplayDateEndChanged));

        /// <summary>
        /// DisplayDateEndProperty property changed handler.
        /// </summary>
        /// <param name="d">DatePicker that changed its DisplayDateEnd.</param>
        /// <param name="e">DependencyPropertyChangedEventArgs.</param>
        private static void OnDisplayDateEndChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DatePicker datePicker = d as DatePicker;
            Debug.Assert(datePicker != null);

            datePicker._calendar.DisplayDateEnd = datePicker.DisplayDateEnd;

            if ( datePicker._calendar.DisplayDateEnd.HasValue && datePicker.DisplayDateEnd.HasValue && DateTime.Compare(datePicker._calendar.DisplayDateEnd.Value, datePicker.DisplayDateEnd.Value) != 0)
            {
                datePicker.DisplayDateEnd = datePicker._calendar.DisplayDateEnd;
            }
        }
        #endregion DisplayDateEnd

        #region DisplayDateStart

        /// <summary>
        /// Gets or sets the first date to be displayed.
        /// </summary>
        /// 
        [TypeConverter(typeof(DateTimeTypeConverter))]
        public DateTime? DisplayDateStart
        {
            get { return (DateTime?)GetValue(DisplayDateStartProperty); }
            set { SetValue(DisplayDateStartProperty, value); }
        }

        /// <summary>
        /// Identifies the DisplayDateStart dependency property.
        /// </summary>
        public static readonly DependencyProperty DisplayDateStartProperty =
            DependencyProperty.Register(
            "DisplayDateStart",
            typeof(DateTime?),
            typeof(DatePicker),
            new PropertyMetadata(OnDisplayDateStartChanged));

        /// <summary>
        /// DisplayDateStartProperty property changed handler.
        /// </summary>
        /// <param name="d">DatePicker that changed its DisplayDateStart.</param>
        /// <param name="e">DependencyPropertyChangedEventArgs.</param>
        private static void OnDisplayDateStartChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DatePicker datePicker = d as DatePicker;
            Debug.Assert(datePicker != null);

            datePicker._calendar.DisplayDateStart = datePicker.DisplayDateStart;

            if (datePicker._calendar.DisplayDateStart.HasValue && datePicker.DisplayDateStart.HasValue && DateTime.Compare(datePicker._calendar.DisplayDateStart.Value, datePicker.DisplayDateStart.Value) != 0)
            {
                datePicker.DisplayDateStart = datePicker._calendar.DisplayDateStart;
            }
        }

        #endregion DisplayDateStart

        #region FirstDayOfWeek

        /// <summary>
        /// Gets or sets the day that is considered the beginning of the week.
        /// </summary>
        public DayOfWeek FirstDayOfWeek
        {
            get { return (DayOfWeek)GetValue(FirstDayOfWeekProperty); }
            set { SetValue(FirstDayOfWeekProperty, value); }
        }

        /// <summary>
        /// Identifies the FirstDayOfWeek dependency property.
        /// </summary>
        public static readonly DependencyProperty FirstDayOfWeekProperty =
            DependencyProperty.Register(
            "FirstDayOfWeek",
            typeof(DayOfWeek),
            typeof(DatePicker),
            new PropertyMetadata(OnFirstDayOfWeekChanged));

        /// <summary>
        /// FirstDayOfWeekProperty property changed handler.
        /// </summary>
        /// <param name="d">DatePicker that changed its FirstDayOfWeek.</param>
        /// <param name="e">DependencyPropertyChangedEventArgs.</param>
        private static void OnFirstDayOfWeekChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DatePicker datePicker = d as DatePicker;
            Debug.Assert(datePicker != null);

            datePicker._calendar.FirstDayOfWeek = datePicker.FirstDayOfWeek;

        }

        #endregion FirstDayOfWeek

        #region IsDropDownOpen

        /// <summary>
        /// Gets or sets a value that indicates whether the drop-down Calendar is open or closed.
        /// </summary>
        public bool IsDropDownOpen
        {
            get { return (bool)GetValue(IsDropDownOpenProperty); }
            set { SetValue(IsDropDownOpenProperty, value); }
        }

        /// <summary>
        /// Identifies the IsDropDownOpen dependency property.
        /// </summary>
        public static readonly DependencyProperty IsDropDownOpenProperty =
            DependencyProperty.Register(
            "IsDropDownOpen",
            typeof(bool),
            typeof(DatePicker),
            new PropertyMetadata(OnIsDropDownOpenChanged));

        /// <summary>
        /// IsDropDownOpenProperty property changed handler.
        /// </summary>
        /// <param name="d">DatePicker that changed its IsDropDownOpen.</param>
        /// <param name="e">DependencyPropertyChangedEventArgs.</param>
        private static void OnIsDropDownOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            
            DatePicker datePicker = d as DatePicker;
            Debug.Assert(datePicker != null);
            bool newValue = (bool)e.NewValue;
            bool oldValue = (bool)e.OldValue;

            if (datePicker._popUp != null && datePicker._popUp.Child != null)
            {
                if (newValue != oldValue)
                {
                    if (datePicker._calendar.DisplayMode != CalendarMode.Month)
                    {
                        datePicker._calendar.DisplayMode = CalendarMode.Month;
                    }

                    if (newValue)
                    {
                        datePicker.OpenDropDown();
                    }
                    else
                    {
                        Debug.Assert(!newValue);
                        datePicker._popUp.IsOpen = false;
                        datePicker.OnCalendarClosed(new RoutedEventArgs());
                    }

                }
            }
        }

        #endregion IsDropDownOpen

        #region IsEnabled

        /// <summary>
        /// Called when the IsEnabled property changes.
        /// </summary>
        /// <param name="sender">Sender object</param>
        /// <param name="e">Property changed args</param>
        private void OnIsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            UpdateDisabledVisual();
        }

        #endregion IsEnabled

        #region IsTodayHighlighted

        /// <summary>
        /// Gets or sets a value that indicates whether the current date will be highlighted.
        /// </summary>
        public bool IsTodayHighlighted
        {
            get { return (bool)GetValue(IsTodayHighlightedProperty); }
            set { SetValue(IsTodayHighlightedProperty, value); }
        }

        /// <summary>
        /// Identifies the IsTodayHighlighted dependency property.
        /// </summary>
        public static readonly DependencyProperty IsTodayHighlightedProperty =
            DependencyProperty.Register(
            "IsTodayHighlighted",
            typeof(bool),
            typeof(DatePicker),
            new PropertyMetadata(OnIsTodayHighlightedChanged));

        /// <summary>
        /// IsTodayHighlightedProperty property changed handler.
        /// </summary>
        /// <param name="d">DatePicker that changed its IsTodayHighlighted.</param>
        /// <param name="e">DependencyPropertyChangedEventArgs.</param>
        private static void OnIsTodayHighlightedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DatePicker datePicker = d as DatePicker;
            Debug.Assert(datePicker != null);

            datePicker._calendar.IsTodayHighlighted = datePicker.IsTodayHighlighted;

        }

        #endregion IsTodayHighlighted

        #region SelectedDate

        /// <summary>
        /// Gets or sets the currently selected date.
        /// </summary>
        /// 
        [TypeConverter(typeof(DateTimeTypeConverter))]
        public DateTime? SelectedDate
        {
            get { return (DateTime?)GetValue(SelectedDateProperty); }
            set { SetValue(SelectedDateProperty, value); }
        }

        /// <summary>
        /// Identifies the SelectedDate dependency property.
        /// </summary>
        public static readonly DependencyProperty SelectedDateProperty =
            DependencyProperty.Register(
            "SelectedDate",
            typeof(DateTime?),
            typeof(DatePicker),
            new PropertyMetadata(OnSelectedDateChanged));

        /// <summary>
        /// SelectedDateProperty property changed handler.
        /// </summary>
        /// <param name="d">DatePicker that changed its SelectedDate.</param>
        /// <param name="e">DependencyPropertyChangedEventArgs.</param>
        private static void OnSelectedDateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Collection<DateTime> addedItems = new Collection<DateTime>();
            Collection<DateTime> removedItems = new Collection<DateTime>();
            DateTime? addedDate;
            DateTime? removedDate;
            DatePicker datePicker = d as DatePicker;
            Debug.Assert(datePicker != null);

            addedDate = (DateTime?)e.NewValue;
            removedDate = (DateTime?)e.OldValue;

            if (addedDate.HasValue)
            {
                addedItems.Add(addedDate.Value);
            }

            if (removedDate.HasValue)
            {
                removedItems.Add(removedDate.Value);
            }

            if (addedDate != datePicker._calendar.SelectedDate)
            {
                datePicker._calendar.SelectedDate = addedDate;
            }

            if (datePicker.SelectedDate != null)
            {
                DateTime day = (DateTime)datePicker.SelectedDate;
                
                //When the SelectedDateProperty change is done from OnTextPropertyChanged method, two-way binding breaks
                //if BeginInvoke is not used:
                datePicker.Dispatcher.BeginInvoke(delegate
                {
                    datePicker._settingSelectedDate = true;
                    datePicker.Text = datePicker.DateTimeToString(day);
                    datePicker._settingSelectedDate = false;
                    datePicker.OnDateSelected(new SelectionChangedEventArgs(removedItems, addedItems));
                });

                //When DatePickerDisplayDateFlag is TRUE, the SelectedDate change is coming from the Calendar UI itself,
                //so, we shouldn't change the DisplayDate since it will automatically be changed by the Calendar
                if ((day.Month != datePicker.DisplayDate.Month || day.Year != datePicker.DisplayDate.Year) && !datePicker._calendar.DatePickerDisplayDateFlag)
                {
                    datePicker.DisplayDate = day;
                }
                datePicker._calendar.DatePickerDisplayDateFlag = false;
            }
            else
            {
                datePicker._settingSelectedDate = true;
                datePicker.SetWaterMarkText();
                datePicker._settingSelectedDate = false;
                datePicker.OnDateSelected(new SelectionChangedEventArgs(removedItems, addedItems));
            }
            
        }

        #endregion SelectedDate

        #region SelectedDateFormat

        /// <summary>
        /// Gets or sets the format that is used to display the selected date.
        /// </summary>
        public DatePickerFormat SelectedDateFormat
        {
            get { return (DatePickerFormat)GetValue(SelectedDateFormatProperty); }
            set { SetValue(SelectedDateFormatProperty, value); }
        }

        /// <summary>
        /// Identifies the SelectedDateFormat dependency property.
        /// </summary>
        public static readonly DependencyProperty SelectedDateFormatProperty =
            DependencyProperty.Register(
            "SelectedDateFormat",
            typeof(DatePickerFormat),
            typeof(DatePicker),
            new PropertyMetadata(OnSelectedDateFormatChanged));

        /// <summary>
        /// SelectedDateFormatProperty property changed handler.
        /// </summary>
        /// <param name="d">DatePicker that changed its SelectedDateFormat.</param>
        /// <param name="e">DependencyPropertyChangedEventArgs.</param>
        private static void OnSelectedDateFormatChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DatePicker datePicker = d as DatePicker;
            Debug.Assert(datePicker != null);

            if (IsValidSelectedDateFormat((DatePickerFormat)e.NewValue))
            {
                if (datePicker._textBox != null)
                {
                    //Update DatePickerTextBox.Text
                    if (string.IsNullOrEmpty(datePicker._textBox.Text))
                    {
                        datePicker.SetWaterMarkText();
                    }
                    else
                    {
                        DateTime? date = datePicker.ParseText(datePicker._textBox.Text);

                        if (date != null)
                        {
                            string s = datePicker.DateTimeToString((DateTime)date);
                            datePicker.Text = s;
                        }
                    }
                }
            }
            else
            {
                throw new ArgumentOutOfRangeException("d", Resource.DatePicker_OnSelectedDateFormatChanged_InvalidValue);
            }

        }

        #endregion SelectedDateFormat

        #region SelectionBackground

        /// <summary>
        /// Gets or sets the SelectedBackground of the DatePickerTextBox.
        /// </summary>
        public Brush SelectionBackground
        {
            get { return (Brush)GetValue(SelectionBackgroundProperty); }
            set { SetValue(SelectionBackgroundProperty, value); }
        }

        /// <summary>
        /// Identifies the SelectionBackground dependency property.
        /// </summary>
        public static readonly DependencyProperty SelectionBackgroundProperty =
            DependencyProperty.Register(
            "SelectionBackground",
            typeof(Brush),
            typeof(DatePicker),
            null);

        #endregion SelectionBackground

        #region Text

        /// <summary>
        /// Gets or sets the text that is displayed by the DatePicker.
        /// </summary>
        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }

        /// <summary>
        /// Identifies the Text dependency property.
        /// </summary>
        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register(
            "Text",
            typeof(string),
            typeof(DatePicker),
            new PropertyMetadata(OnTextChanged));

        /// <summary>
        /// TextProperty property changed handler.
        /// </summary>
        /// <param name="d">DatePicker that changed its Text.</param>
        /// <param name="e">DependencyPropertyChangedEventArgs.</param>
        private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DatePicker datePicker = d as DatePicker;
            Debug.Assert(datePicker != null);

            if (!datePicker.IsHandlerSuspended(DatePicker.TextProperty))
            {
                string newValue = e.NewValue as String;

                if (newValue != null)
                {
                    if (datePicker._textBox != null)
                    {
                        datePicker._textBox.Text = newValue;
                    }
                    else
                    {
                        datePicker._defaultText = newValue;
                    }
                    if (!datePicker._settingSelectedDate)
                    {
                        datePicker.SetSelectedDate();
                    }
                }
                else
                {
                    if (!datePicker._settingSelectedDate)
                    {
                        datePicker.SetValueNoCallback(DatePicker.SelectedDateProperty, null);
                    }
                }
            }
        }

        #endregion Text

        #endregion Public Properties

        #region Protected properties

        #endregion Protected Properties

        #region Internal Properties

        #endregion Internal Properties

        #region Private Properties
        #endregion Private Properties

        #region Public Methods

        /// <summary>
        /// Builds the visual tree for the DatePicker control when a new template is applied.
        /// </summary>
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            if (_popUp != null)
            {
                _popUp.Child = null;
            }

            _popUp = GetTemplateChild(ElementPopup) as Popup;

            if (_popUp != null)
            {
                if (this._outsideCanvas == null)
                {
                    _outsideCanvas = new Canvas();
                    _outsidePopupCanvas = new Canvas();
                    _outsidePopupCanvas.Background = new SolidColorBrush(Colors.Transparent);
                    _outsideCanvas.Children.Add(this._outsidePopupCanvas);
                    _outsideCanvas.Children.Add(this._calendar);
                    _outsidePopupCanvas.MouseLeftButtonDown += new MouseButtonEventHandler(OutsidePopupCanvas_MouseLeftButtonDown);
                }
                
                _popUp.Child = this._outsideCanvas;
                _root = GetTemplateChild(ElementRoot) as FrameworkElement;

                if (this.IsDropDownOpen)
                {
                    OpenDropDown();
                }
            }

            if (_dropDownButton != null)
            {
                _dropDownButton.Click -= new RoutedEventHandler(DropDownButton_Click);
            }

            _dropDownButton = GetTemplateChild(ElementButton) as Button;
            if (_dropDownButton != null)
            {
                _dropDownButton.Click += new RoutedEventHandler(DropDownButton_Click);
                _dropDownButton.IsTabStop = false;

                //If the user does not provide a Content value in template, we provide a helper text that can be used in Accessibility
                //this text is not shown on the UI, just used for Accessibility purposes
                if (_dropDownButton.Content == null)
                {
                    _dropDownButton.Content = Resource.DatePicker_DropDownButtonName;
                }
            }

            if (_textBox != null)
            {
                _textBox.KeyDown -= new KeyEventHandler(TextBox_KeyDown);
                _textBox.TextChanged -= new TextChangedEventHandler(TextBox_TextChanged);
                _textBox.GotFocus -= new RoutedEventHandler(TextBox_GotFocus);
            }

            _textBox = GetTemplateChild(ElementTextBox) as DatePickerTextBox;

            UpdateDisabledVisual();
            if (this.SelectedDate == null)
            {
                SetWaterMarkText();
            }

            if (_textBox != null)
            {
                _textBox.KeyDown += new KeyEventHandler(TextBox_KeyDown);
                _textBox.TextChanged += new TextChangedEventHandler(TextBox_TextChanged);
                _textBox.GotFocus += new RoutedEventHandler(TextBox_GotFocus);

                if (this.SelectedDate == null)
                {

                    if (!string.IsNullOrEmpty(this._defaultText))
                    {
                        _textBox.Text = this._defaultText;
                        SetSelectedDate();
                    }
                }
                else
                {
                    _textBox.Text = this.DateTimeToString((DateTime)this.SelectedDate);
                }
            }
        }

        /// <summary>
        /// Provides a text representation of the selected date.
        /// </summary>
        /// <returns>A text representation of the selected date, or an empty string if SelectedDate is a null reference.</returns>
        public override string ToString()
        {
            if (this.SelectedDate != null)
            {
                return this.SelectedDate.Value.ToString(DateTimeHelper.GetCurrentDateFormat());
            }
            else
            {
                return string.Empty;
            }
        }

        #endregion Public Methods

        #region Protected Methods

        /// <summary>
        /// Creates the automation peer for this DatePicker Control.
        /// </summary>
        /// <returns></returns>
        protected override AutomationPeer OnCreateAutomationPeer()
        {
            return new DatePickerAutomationPeer(this);
        }

        /// <summary>
        /// Raises the DateValidationError event.
        /// </summary>
        /// <param name="e">A DatePickerDateValidationErrorEventArgs that contains the event data.</param>
        protected virtual void OnDateValidationError(DatePickerDateValidationErrorEventArgs e)
        {
            EventHandler<DatePickerDateValidationErrorEventArgs> handler = this.DateValidationError;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        #endregion Protected Methods

        #region Internal Methods
        #endregion Internal Methods

        #region Private Methods

        private void Calendar_DayButtonMouseUp(object sender, MouseButtonEventArgs e)
        {
            this.Focus();
            this.IsDropDownOpen = false;
            _calendar.ReleaseMouseCapture();      
        }

        private void Calendar_DisplayDateChanged(object sender, CalendarDateChangedEventArgs e)
        {
            if (e.AddedDate != this.DisplayDate)
            {
                SetValue(DisplayDateProperty, (DateTime)e.AddedDate);
            }
        }

        private void Calendar_KeyDown(object sender, KeyEventArgs e)
        {
            Calendar c = sender as Calendar;
            Debug.Assert(c != null);

            if (!e.Handled && (e.Key == Key.Enter || e.Key == Key.Space || e.Key == Key.Escape) && c.DisplayMode == CalendarMode.Month)
            {
                this.Focus();
                this.IsDropDownOpen = false;
            }
        }

        private void Calendar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            e.Handled = true;
        }

        private void Calendar_SelectedDatesChanged(object sender, SelectionChangedEventArgs e)
        {
            Debug.Assert(e.AddedItems.Count < 2);

            if (e.AddedItems.Count > 0 && this.SelectedDate.HasValue && DateTime.Compare((DateTime)e.AddedItems[0], this.SelectedDate.Value) != 0)
            {
                this.SelectedDate = (DateTime?)e.AddedItems[0];
            }
            else
            {
                if (e.AddedItems.Count == 0)
                {
                    this.SelectedDate = null;
                    return;
                }

                if (!this.SelectedDate.HasValue)
                {
                    if (e.AddedItems.Count > 0)
                    {
                        this.SelectedDate = (DateTime?)e.AddedItems[0];
                    }
                }
            }
        }

        private void Calendar_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            SetPopUpPosition();
        }

        private string DateTimeToString(DateTime d)
        {
            DateTimeFormatInfo dtfi = DateTimeHelper.GetCurrentDateFormat();

            switch (this.SelectedDateFormat)
            {
                case DatePickerFormat.Short:
                    {
                        return string.Format(CultureInfo.CurrentCulture, d.ToString(dtfi.ShortDatePattern, dtfi));
                    }
                case DatePickerFormat.Long:
                    {
                        return string.Format(CultureInfo.CurrentCulture, d.ToString(dtfi.LongDatePattern, dtfi));
                    }
            }      
            return null;
        }

        private void DatePicker_LostFocus(object sender, RoutedEventArgs e)
        {
            DatePicker datePicker = sender as DatePicker;
            Debug.Assert(datePicker != null);
            Debug.Assert(e.OriginalSource != null);

            if (datePicker.IsDropDownOpen && datePicker._dropDownButton != null && !(e.OriginalSource.Equals(datePicker._textBox)) && !(e.OriginalSource.Equals(datePicker._dropDownButton)) && !(e.OriginalSource.Equals(datePicker._calendar)))
            {
                datePicker.IsDropDownOpen = false;
            }
            SetSelectedDate();
        }

        private void DatePicker_GotFocus(object sender, RoutedEventArgs e)
        {
            DatePicker datePicker = sender as DatePicker;
            Debug.Assert(datePicker != null);
            if (this.IsEnabled && this._textBox != null)
            {
                this._textBox.Focus();
            }
        }

        private static DateTime DiscardDayTime(DateTime d)
        {
            int year = d.Year;
            int month = d.Month;
            DateTime newD = new DateTime(year, month, 1, 0, 0, 0);
            return newD;
        }

        private static DateTime? DiscardTime(DateTime? d)
        {
            if (d == null)
            {
                return null;
            }
            else
            {
                DateTime discarded = (DateTime)d;
                int year = discarded.Year;
                int month = discarded.Month;
                int day = discarded.Day;
                DateTime newD = new DateTime(year, month, day, 0, 0, 0);
                return newD;
            }
        }

        private void DropDownButton_Click(object sender, RoutedEventArgs e)
        {
            HandlePopUp();
        }

        private void HandlePopUp()
        {
            if (this.IsDropDownOpen)
            {
                this.Focus();
                this.IsDropDownOpen = false;
                _calendar.ReleaseMouseCapture();
            }
            else
            {
                Debug.Assert(!this.IsDropDownOpen);
                _calendar.CaptureMouse();
                ProcessTextBox();
            }
        }

        private void InitializeCalendar()
        {
            _calendar = new Calendar();
            _calendar.DayButtonMouseUp += new MouseButtonEventHandler(Calendar_DayButtonMouseUp);
            _calendar.DisplayDateChanged += new EventHandler<CalendarDateChangedEventArgs>(Calendar_DisplayDateChanged);
            _calendar.SelectedDatesChanged += new EventHandler<SelectionChangedEventArgs>(Calendar_SelectedDatesChanged);
            _calendar.MouseLeftButtonDown += new MouseButtonEventHandler(Calendar_MouseLeftButtonDown);
            _calendar.KeyDown += new KeyEventHandler(Calendar_KeyDown);
            _calendar.SelectionMode = CalendarSelectionMode.SingleDate;
            _calendar.SizeChanged += new SizeChangedEventHandler(Calendar_SizeChanged);
            _calendar.IsTabStop = true;
        }

        /// <summary>
        /// Sets the matrix to its inverse
        /// </summary>
        /// <param name="matrix">Matrix to be inverted.</param>
        /// <returns>
        /// bool - true if the Matrix is invertible, false otherwise.
        /// </returns>
        private static bool InvertMatrix(ref Matrix matrix)
        {
            double determinant = matrix.M11 * matrix.M22 - matrix.M12 * matrix.M21;

            if (determinant == 0.0)
            {
                return false;
            }

            Matrix matCopy = matrix;
            matrix.M11 = matCopy.M22 / determinant;
            matrix.M12 = -1 * matCopy.M12 / determinant;
            matrix.M21 = -1 * matCopy.M21 / determinant;
            matrix.M22 = matCopy.M11 / determinant;
            matrix.OffsetX = (matCopy.OffsetY * matCopy.M21 - matCopy.OffsetX * matCopy.M22) / determinant;
            matrix.OffsetY = (matCopy.OffsetX * matCopy.M12 - matCopy.OffsetY * matCopy.M11) / determinant;

            return true;
        }

        private static bool IsValidSelectedDateFormat(DatePickerFormat value)
        {
            DatePickerFormat format = (DatePickerFormat)value;

            return format == DatePickerFormat.Long
                || format == DatePickerFormat.Short;
        }

        private void OnCalendarClosed(RoutedEventArgs e)
        {
            RoutedEventHandler handler = this.CalendarClosed;
            if (null != handler)
            {
                handler(this, e);
            }
        }

        private void OnCalendarOpened(RoutedEventArgs e)
        {
            RoutedEventHandler handler = this.CalendarOpened;
            if (null != handler)
            {
                handler(this, e);
            }
        }

        private void OnDateSelected(SelectionChangedEventArgs e)
        {
            EventHandler<SelectionChangedEventArgs> handler = this.SelectedDateChanged;
            if (null != handler)
            {
                handler(this, e);
            }
        }

        private void OpenDropDown()
        {
            OpenPopUp();
            this._calendar.Focus();
            this._calendar.ResetStates();
            this.OnCalendarOpened(new RoutedEventArgs());
        }

        private void OpenPopUp()
        {
            FrameworkElement page = (Application.Current != null) ?
                       Application.Current.RootVisual as FrameworkElement :
                       null;

            if (page != null)
            {            
                 this._popUp.IsOpen = true;
            }
        }

        private void OutsidePopupCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            this.IsDropDownOpen = false;
        }

        

        /// <summary>
        /// Input text is parsed in the correct format and changed into a DateTime object.
        /// If the text can not be parsed TextParseError Event is thrown.
        /// </summary>
        private DateTime? ParseText(string text)
        {
            DateTime newSelectedDate;

            //TryParse is not used in order to be able to pass the exception to the TextParseError event
            try
            {
                newSelectedDate = DateTime.Parse(text, DateTimeHelper.GetCurrentDateFormat());

                if (Calendar.IsValidDateSelection(this._calendar, newSelectedDate))
                {
                    return newSelectedDate;
                }
                else
                {
                    DatePickerDateValidationErrorEventArgs dateValidationError = new DatePickerDateValidationErrorEventArgs(new ArgumentOutOfRangeException("text",Resource.Calendar_OnSelectedDateChanged_InvalidValue), text);
                    OnDateValidationError(dateValidationError);

                    if (dateValidationError.ThrowException)
                    {
                        throw dateValidationError.Exception;
                    }
                }
            }
            catch (FormatException ex)
            {
                DatePickerDateValidationErrorEventArgs textParseError = new DatePickerDateValidationErrorEventArgs(ex, text);
                OnDateValidationError(textParseError);

                if (textParseError.ThrowException)
                {
                    throw textParseError.Exception;
                }
            }
            return null;
        }

        private bool ProcessDatePickerKey(KeyEventArgs e)
        {
            switch (e.Key)
            {
                case Key.Enter:
                    {
                        SetSelectedDate();
                        return true;
                    }
                case Key.Down:
                    {
                        // 
                        if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
                        {
                            HandlePopUp();
                        }
                        return true;
                    }
            }
            return false;
        }

        private void ProcessTextBox()
        {
            SetSelectedDate();
            this.IsDropDownOpen = true;
            _calendar.Focus();
        }

        private void SetPopUpPosition()
        {
            if (this._calendar != null && Application.Current != null && Application.Current.Host != null && Application.Current.Host.Content != null)
            {
                double pageHeight = Application.Current.Host.Content.ActualHeight;
                double pageWidth = Application.Current.Host.Content.ActualWidth;
                double calendarHeight = this._calendar.ActualHeight;
                double dpHeight = this.ActualHeight;
           
                if ( this._root != null)
                {
                    MatrixTransform mt = this._root.TransformToVisual(null) as MatrixTransform;

                    if ( mt != null)
                    {
                        double dpX = mt.Matrix.OffsetX;
                        double dpY = mt.Matrix.OffsetY;

                        double calendarX = dpX;
                        double calendarY = dpY + dpHeight;

                        //if the page height is less then the total height of the PopUp + DatePicker
                        //or if we can fit the PopUp inside the page, we want to place the PopUp to the bottom
                        if ( pageHeight < calendarY + calendarHeight)
                        {
                            calendarY = dpY - calendarHeight;
                        }
                        this._popUp.HorizontalOffset = 0;
                        this._popUp.VerticalOffset = 0;
                        this._outsidePopupCanvas.Width = pageWidth;
                        this._outsidePopupCanvas.Height = pageHeight;
                        this._calendar.HorizontalAlignment = HorizontalAlignment.Left;
                        this._calendar.VerticalAlignment = VerticalAlignment.Top;
                        Canvas.SetLeft(this._calendar, calendarX - dpX);
                        Canvas.SetTop(this._calendar, calendarY - dpY);

                        //transform the invisible canvas to plugin coordinate space origin
                        Matrix transformToRootMatrix = mt.Matrix;
                        if (InvertMatrix(ref transformToRootMatrix))
                        {
                            mt.Matrix = transformToRootMatrix;
                            this._outsidePopupCanvas.RenderTransform = mt;
                        }
                    }
                }
            }
        }

        private void SetSelectedDate()
        {
            if (this._textBox != null)
            {
                if (!string.IsNullOrEmpty(this._textBox.Text))
                {
                    string s = this._textBox.Text;

                    if (this.SelectedDate != null)
                    {
                        //If the string value of the SelectedDate and the TextBox string value are equal,
                        //we do not parse the string again
                        //if we do an extra parse, we lose data in M/d/yy format
                        // ex: SelectedDate = DateTime(1008,12,19) but when "12/19/08" is parsed it is interpreted as DateTime(2008,12,19)

                        string selectedDate = DateTimeToString(this.SelectedDate.Value);

                        if (selectedDate == s)
                        {
                            return;
                        }
                    }
                    DateTime? d = SetTextBoxValue(s);
                    if (!this.SelectedDate.Equals(d))
                    {
                        this.SelectedDate = d;
                    }
                }
                else
                {
                    if (this.SelectedDate != null)
                    {
                        this.SelectedDate = null;
                    }
                }
            }
            else
            {
                DateTime? d = SetTextBoxValue(_defaultText);
                if (!this.SelectedDate.Equals(d))
                {
                    this.SelectedDate = d;
                }
            }
        }

        private DateTime? SetTextBoxValue(string s)
        {
            if (string.IsNullOrEmpty(s))
            {
                SetValue(TextProperty, s);
                return this.SelectedDate;
            }
            else
            {
                DateTime? d = ParseText(s);

                if (d != null)
                {
                    SetValue(TextProperty, s);
                    return d;
                }
                else
                {
                    ////If parse error:
                    //TextBox should have the latest valid selecteddate value:
                    if (this.SelectedDate != null)
                    {
                        string newtext = this.DateTimeToString((DateTime)this.SelectedDate);
                        SetValue(TextProperty, newtext);
                        return this.SelectedDate;
                    }
                    else
                    {
                        SetWaterMarkText();
                        return null;
                    }
                }
            }
        }

        private void SetWaterMarkText()
        {
            if (this._textBox != null)
            {
                DateTimeFormatInfo dtfi = DateTimeHelper.GetCurrentDateFormat();
                this.Text = string.Empty;
                this._defaultText = string.Empty;

                switch (this.SelectedDateFormat)
                {
                    case DatePickerFormat.Long:
                        {
                            this._textBox.Watermark = string.Format(CultureInfo.CurrentCulture, Resource.DatePicker_WatermarkText, dtfi.LongDatePattern.ToString());
                            break;
                        }
                    case DatePickerFormat.Short:
                        {
                            this._textBox.Watermark = string.Format(CultureInfo.CurrentCulture, Resource.DatePicker_WatermarkText, dtfi.ShortDatePattern.ToString());
                            break;
                        }
                }
            }
        }

        private void TextBox_GotFocus(object sender, RoutedEventArgs e)
        {
            this.IsDropDownOpen = false;
        }

        private void TextBox_KeyDown(object sender, KeyEventArgs e)
        {
            if (!e.Handled)
            {
                e.Handled = ProcessDatePickerKey(e);
            }
        }

        private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            this.SetValueNoCallback(DatePicker.TextProperty, this._textBox.Text);
        }

        private void UpdateDisabledVisual()
        {
            if (!IsEnabled)
            {
                VisualStates.GoToState(this, true, VisualStates.StateDisabled, VisualStates.StateNormal);
            }
            else
            {
                VisualStates.GoToState(this, true, VisualStates.StateNormal);
            }

        }

        #endregion Private Methods

    }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.