148 lines
5.7 KiB
C#
148 lines
5.7 KiB
C#
using System;
|
|
using System.Windows.Input;
|
|
using CommunityToolkit.Diagnostics;
|
|
using Windows.UI;
|
|
using Windows.UI.Xaml;
|
|
using Windows.UI.Xaml.Controls;
|
|
using Windows.UI.Xaml.Media;
|
|
using Wino.Core.Domain.Models.Calendar;
|
|
using Wino.Helpers;
|
|
|
|
namespace Wino.Calendar.Controls;
|
|
|
|
public partial class WinoCalendarView : Control
|
|
{
|
|
private const string PART_DayViewItemBorder = nameof(PART_DayViewItemBorder);
|
|
private const string PART_CalendarView = nameof(PART_CalendarView);
|
|
|
|
public static readonly DependencyProperty HighlightedDateRangeProperty = DependencyProperty.Register(nameof(HighlightedDateRange), typeof(DateRange), typeof(WinoCalendarView), new PropertyMetadata(null, new PropertyChangedCallback(OnHighlightedDateRangeChanged)));
|
|
public static readonly DependencyProperty VisibleDateBackgroundProperty = DependencyProperty.Register(nameof(VisibleDateBackground), typeof(Brush), typeof(WinoCalendarView), new PropertyMetadata(null, new PropertyChangedCallback(OnPropertiesChanged)));
|
|
public static readonly DependencyProperty DateClickedCommandProperty = DependencyProperty.Register(nameof(DateClickedCommand), typeof(ICommand), typeof(WinoCalendarView), new PropertyMetadata(null));
|
|
public static readonly DependencyProperty TodayBackgroundColorProperty = DependencyProperty.Register(nameof(TodayBackgroundColor), typeof(Color), typeof(WinoCalendarView), new PropertyMetadata(null));
|
|
|
|
public Color TodayBackgroundColor
|
|
{
|
|
get { return (Color)GetValue(TodayBackgroundColorProperty); }
|
|
set { SetValue(TodayBackgroundColorProperty, value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the command to execute when a date is picked.
|
|
/// Unused.
|
|
/// </summary>
|
|
public ICommand DateClickedCommand
|
|
{
|
|
get { return (ICommand)GetValue(DateClickedCommandProperty); }
|
|
set { SetValue(DateClickedCommandProperty, value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the highlighted range of dates.
|
|
/// </summary>
|
|
public DateRange HighlightedDateRange
|
|
{
|
|
get { return (DateRange)GetValue(HighlightedDateRangeProperty); }
|
|
set { SetValue(HighlightedDateRangeProperty, value); }
|
|
}
|
|
|
|
public Brush VisibleDateBackground
|
|
{
|
|
get { return (Brush)GetValue(VisibleDateBackgroundProperty); }
|
|
set { SetValue(VisibleDateBackgroundProperty, value); }
|
|
}
|
|
|
|
|
|
|
|
private CalendarView CalendarView;
|
|
|
|
public WinoCalendarView()
|
|
{
|
|
DefaultStyleKey = typeof(WinoCalendarView);
|
|
}
|
|
|
|
protected override void OnApplyTemplate()
|
|
{
|
|
base.OnApplyTemplate();
|
|
|
|
CalendarView = GetTemplateChild(PART_CalendarView) as CalendarView;
|
|
|
|
Guard.IsNotNull(CalendarView, nameof(CalendarView));
|
|
|
|
CalendarView.SelectedDatesChanged -= InternalCalendarViewSelectionChanged;
|
|
CalendarView.SelectedDatesChanged += InternalCalendarViewSelectionChanged;
|
|
|
|
// TODO: Should come from settings.
|
|
CalendarView.FirstDayOfWeek = Windows.Globalization.DayOfWeek.Monday;
|
|
|
|
// Everytime display mode changes, update the visible date range backgrounds.
|
|
// If users go back from year -> month -> day, we need to update the visible date range backgrounds.
|
|
|
|
CalendarView.RegisterPropertyChangedCallback(CalendarView.DisplayModeProperty, (s, e) => UpdateVisibleDateRangeBackgrounds());
|
|
}
|
|
|
|
private void InternalCalendarViewSelectionChanged(CalendarView sender, CalendarViewSelectedDatesChangedEventArgs args)
|
|
{
|
|
if (args.AddedDates?.Count > 0)
|
|
{
|
|
var clickedDate = args.AddedDates[0].Date;
|
|
SetInnerDisplayDate(clickedDate);
|
|
|
|
var clickArgs = new CalendarViewDayClickedEventArgs(clickedDate);
|
|
DateClickedCommand?.Execute(clickArgs);
|
|
}
|
|
|
|
// Reset selection, we don't show selected dates but react to them.
|
|
CalendarView.SelectedDates.Clear();
|
|
}
|
|
|
|
private static void OnPropertiesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
{
|
|
if (d is WinoCalendarView control)
|
|
{
|
|
control.UpdateVisibleDateRangeBackgrounds();
|
|
}
|
|
}
|
|
|
|
private void SetInnerDisplayDate(DateTime dateTime) => CalendarView?.SetDisplayDate(dateTime);
|
|
|
|
// Changing selected dates will trigger the selection changed event.
|
|
// It will behave like user clicked the date.
|
|
public void GoToDay(DateTime dateTime) => CalendarView.SelectedDates.Add(dateTime);
|
|
|
|
private static void OnHighlightedDateRangeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
{
|
|
if (d is WinoCalendarView control)
|
|
{
|
|
control.SetInnerDisplayDate(control.HighlightedDateRange.StartDate);
|
|
control.UpdateVisibleDateRangeBackgrounds();
|
|
}
|
|
}
|
|
|
|
public void UpdateVisibleDateRangeBackgrounds()
|
|
{
|
|
if (HighlightedDateRange == null || VisibleDateBackground == null || TodayBackgroundColor == null || CalendarView == null) return;
|
|
|
|
var markDateCalendarDayItems = WinoVisualTreeHelper.FindDescendants<CalendarViewDayItem>(CalendarView);
|
|
|
|
foreach (var calendarDayItem in markDateCalendarDayItems)
|
|
{
|
|
var border = WinoVisualTreeHelper.GetChildObject<Border>(calendarDayItem, PART_DayViewItemBorder);
|
|
|
|
if (border == null) return;
|
|
|
|
if (calendarDayItem.Date.Date == DateTime.Today.Date)
|
|
{
|
|
border.Background = new SolidColorBrush(TodayBackgroundColor);
|
|
}
|
|
else if (calendarDayItem.Date.Date >= HighlightedDateRange.StartDate.Date && calendarDayItem.Date.Date < HighlightedDateRange.EndDate.Date)
|
|
{
|
|
border.Background = VisibleDateBackground;
|
|
}
|
|
else
|
|
{
|
|
border.Background = null;
|
|
}
|
|
}
|
|
}
|
|
}
|