xamlwinui-3winuiwindows-app-sdkwinui-xaml

How can I hide the dates that are not part of the current month in the CalendarView control in WinUI 3?


I am using the CalendarView control in my WinUI 3 project. I want to hide the out-of-scope dates. I didn’t find any property for this. I can set the OutOfScopeForeground to match the calendar background, but that only hides the dates visually. I can still select them.

I have marked the out-of-scope dates in the image below. How can I disable them?

enter image description here


Solution

  • I guess, you'll need to create a custom (templated) control, something like this:

    public partial class CalendarViewEx : CalendarView
    {
        public CalendarViewEx()
        {
            this.DefaultStyleKey = typeof(CalendarViewEx);
            Loaded += CalendarViewEx_Loaded;
            Unloaded += CalendarViewEx_Unloaded;
        }
    
        private long HeaderButtonContentChangeToken { get; set; }
    
        private Button? HeaderButton { get; set; }
    
        private void CalendarViewEx_Loaded(object sender, RoutedEventArgs e)
        {
            if (GetTemplateChild("HeaderButton") is Button headerButton)
            {
                HeaderButton = headerButton;
                HeaderButtonContentChangeToken = HeaderButton.RegisterPropertyChangedCallback(Button.ContentProperty, OnHeaderButtonContentPropertyChanged);
            }
    
            RefreshCalenderViewDayItems();
        }
    
        private void CalendarViewEx_Unloaded(object sender, RoutedEventArgs e)
        {
            if (HeaderButton is not null)
            {
                HeaderButton.UnregisterPropertyChangedCallback(Button.ContentProperty, HeaderButtonContentChangeToken);
                HeaderButton = null;
            }
        }
    
        private void OnHeaderButtonContentPropertyChanged(DependencyObject sender, DependencyProperty dp)
        {
            RefreshCalenderViewDayItems();
        }
    
        private void RefreshCalenderViewDayItems()
        {
            if (HeaderButton?.Content is not string headerText)
            {
                return;
            }
    
            // Removes hidden unicode characters.
            var cleanedHeaderText = new string([.. headerText.Where(c => !char.IsControl(c) && CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.Format)]);
    
            // You might need to modify this according to the language.
            if (!DateTime.TryParseExact(cleanedHeaderText, "MMMM yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out var headerDate))
            {
                System.Diagnostics.Debug.WriteLine($"Failed to parse header text: {headerText}");
                return;
            }
    
            foreach (CalendarViewDayItem item in this.FindDescendants().OfType<CalendarViewDayItem>())
            {
                item.Visibility = item.Date.Month != headerDate.Month ? Visibility.Collapsed : Visibility.Visible;
            }
        }
    }
    
    <Style TargetType="local:CalendarViewEx" BasedOn="{StaticResource DefaultCalendarViewStyle}" />