using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Data; using System.Windows.Input; // ReSharper disable once CheckNamespace namespace WPFluent.Controls; /// /// Represents a control that allows a user to pick a date from a calendar display. /// /// /// <ui:CalendarDatePicker /> /// public class CalendarDatePicker : Button { /// /// Identifies the dependency property. /// public static readonly DependencyProperty DateProperty = DependencyProperty.Register( nameof(Date), typeof(DateTime?), typeof(CalendarDatePicker), new PropertyMetadata(null)); /// /// Identifies the dependency property. /// public static readonly DependencyProperty FirstDayOfWeekProperty = DependencyProperty.Register( nameof(FirstDayOfWeek), typeof(DayOfWeek), typeof(CalendarDatePicker), new PropertyMetadata(DateTimeHelper.GetCurrentDateFormat().FirstDayOfWeek)); /// /// Identifies the dependency property. /// public static readonly DependencyProperty IsCalendarOpenProperty = DependencyProperty.Register( nameof(IsCalendarOpen), typeof(bool), typeof(CalendarDatePicker), new PropertyMetadata(false)); /// /// Identifies the dependency property. /// public static readonly DependencyProperty IsTodayHighlightedProperty = DependencyProperty.Register( nameof(IsTodayHighlighted), typeof(bool), typeof(CalendarDatePicker), new PropertyMetadata(false)); private Popup _popup; private void InitializePopup() { if(_popup is not null) { return; } var calendar = new System.Windows.Controls.Calendar(); calendar.SetBinding( System.Windows.Controls.Calendar.SelectedDateProperty, new Binding(nameof(Date)) { Source = this, Mode = BindingMode.TwoWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged, }); calendar.SetBinding( System.Windows.Controls.Calendar.IsTodayHighlightedProperty, new Binding(nameof(IsTodayHighlighted)) { Source = this, Mode = BindingMode.TwoWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged, }); calendar.SetBinding( System.Windows.Controls.Calendar.FirstDayOfWeekProperty, new Binding(nameof(FirstDayOfWeek)) { Source = this, Mode = BindingMode.TwoWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged, }); calendar.SelectedDatesChanged += OnSelectedDatesChanged; _popup = new Popup { PlacementTarget = this, Placement = PlacementMode.Bottom, Child = calendar, Focusable = false, StaysOpen = false, VerticalOffset = 1D, VerticalAlignment = VerticalAlignment.Center, PopupAnimation = PopupAnimation.None, AllowsTransparency = true, }; _popup.SetBinding( Popup.IsOpenProperty, new Binding(nameof(IsCalendarOpen)) { Source = this, Mode = BindingMode.TwoWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged, }); } /// protected override void OnClick() { base.OnClick(); InitializePopup(); SetCurrentValue(IsCalendarOpenProperty, !IsCalendarOpen); } protected virtual void OnPopupOpened(object sender, EventArgs e) { if(sender is not Popup popup) { return; } if(popup.Child is null) { return; } popup.Focus(); Keyboard.Focus(popup.Child); } protected virtual void OnSelectedDatesChanged(object sender, SelectionChangedEventArgs e) { if(IsCalendarOpen) { SetCurrentValue(IsCalendarOpenProperty, false); } } /// /// Gets or sets the date currently set in the calendar picker. /// [Bindable(true)] public DateTime? Date { get => (DateTime?)GetValue(DateProperty); set => SetValue(DateProperty, value); } /// /// Gets or sets the day that is considered the beginning of the week. /// public DayOfWeek FirstDayOfWeek { get { return (DayOfWeek)GetValue(FirstDayOfWeekProperty); } set { SetValue(FirstDayOfWeekProperty, value); } } /// /// Gets or sets a value indicating whether the calendar view of the is currently /// shown. /// [Bindable(true)] public bool IsCalendarOpen { get => (bool)GetValue(IsCalendarOpenProperty); set => SetValue(IsCalendarOpenProperty, value); } /// /// Gets or sets a value indicating whether the current date is highlighted. /// public bool IsTodayHighlighted { get { return (bool)GetValue(IsTodayHighlightedProperty); } set { SetValue(IsTodayHighlightedProperty, value); } } }