Displaying dates as holiday in WPF Calendar

本小妞迷上赌 提交于 2021-02-10 22:26:32

问题


I'm using WPF Calendar control to add Holidays. User can select days and the selected days will be inserted to a database table as holiday. After the insertion, I'm displaying the days in Holiday table as BlackoutDates in the calendar as in the following code.

XAML

 <Calendar x:Name="HolidayCalendar" SelectedDatesChanged="Calendar_SelectionChanged"
    SelectionMode="MultipleRange" Loaded="Calendar_Loaded"> 

C#

DateTime now = DateTime.Now;
var startDate = new DateTime(now.Year, now.Month, 1);
var endDate = startDate.AddMonths(1).AddDays(-1);
GetHolidayService getHolidayService = new GetHolidayService();
ObservableCollection<GetHoliday> GetHolidayBaseList = new ObservableCollection<GetHoliday>();
PostHoliday postHoliday = new PostHoliday();
postHoliday.StartDate = startDate;
postHoliday.EndDate = endDate;
GetHolidayBaseList = getHolidayService.GetHolidayServiceFunction(postHoliday);
foreach (var item in GetHolidayList)
{

   HolidayCalendar.BlackoutDates.Add(new CalendarDateRange(item.HolidayDate,item.HolidayDate)) ;
}

Current output

I want to achieve something like this - Holidays marked as Red

as in this link

Any help to write a control template required for this functionality is appreciated.

Thanks in advance!


回答1:


This is how you can do it,

First define custom style for CalendarDataButton based on standard style

    <Calendar x:Name="HolidayCalendar" SelectionMode="MultipleRange">
        <Calendar.CalendarDayButtonStyle>
            <Style TargetType="CalendarDayButton" BasedOn="{StaticResource {x:Type CalendarDayButton}}">
                <Style.Triggers>
                    <Trigger Property="IsBlackedOut" Value="True">
                        <Setter Property="Background" Value="DeepPink"/>
                        <Setter Property="local:CalenderHelper.IsBlackOutDisabled" Value="True"/>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </Calendar.CalendarDayButtonStyle>
        <Calendar.BlackoutDates>
            <CalendarDateRange Start="21-Nov-2018" End="21-Nov-2018"/>
            <CalendarDateRange Start="25-Nov-2018" End="25-Nov-2018"/>
        </Calendar.BlackoutDates>
    </Calendar>

In order to remove the strike mark from Blackout date, you will have to use the below attached property 'IsBlackOutDisabled'

public class CalenderHelper : DependencyObject
{
    public static readonly DependencyProperty IsBlackOutDisabledProperty =
        DependencyProperty.RegisterAttached("IsBlackOutDisabled", typeof(bool), typeof(CalenderHelper), new PropertyMetadata(false, OnIsBlackOutDisabledChanged));

    public static bool GetIsBlackOutDisabled(DependencyObject obj)
    {
        return (bool)obj.GetValue(IsBlackOutDisabledProperty);
    }

    public static void SetIsBlackOutDisabled(DependencyObject obj, bool value)
    {
        obj.SetValue(IsBlackOutDisabledProperty, value);
    }

    private static void OnIsBlackOutDisabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        CalendarDayButton dayButton = d as CalendarDayButton;
        if (dayButton.IsLoaded)
        {
            SetBlackout(dayButton, (bool)e.NewValue);
        }
        else
        {
            dayButton.Loaded += (s, ee) =>
            {
                SetBlackout(dayButton, (bool)e.NewValue);
            };
        }
    }

    static void SetBlackout(CalendarDayButton dayButton, bool collapsed)
    {
        ControlTemplate template = dayButton.Template;
        Path blackoutPath = template.FindName("Blackout", dayButton) as Path;
        if (collapsed)
            blackoutPath.Visibility = System.Windows.Visibility.Collapsed;
        else
            blackoutPath.Visibility = System.Windows.Visibility.Visible;
    }
}

UPDATE:

If you want the colored dates to be selectable by Calendar, you must go with different approach. Blackout Dates will not work for you.

This approach takes the converter to color the dates.

First define custom style for CalendarDataButton based on standard style

<Window.Resources>
    <local:CustomLetterDayConverter x:Key="CustomLetterDayConverter" />
    <Style x:Key="CalendarDayButtonStyle" TargetType="{x:Type CalendarDayButton}">
        <Style.Triggers>
            <DataTrigger Binding="{Binding Converter={StaticResource CustomLetterDayConverter}}" Value="{x:Null}">
                <Setter Property="Background" Value="HotPink"></Setter>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</Window.Resources>
<Grid>
    <Calendar x:Name="HolidayCalendar" SelectionMode="MultipleRange" SelectedDate="{Binding SelectedDate}"
              CalendarDayButtonStyle="{StaticResource CalendarDayButtonStyle}"
              >
    </Calendar>
</Grid>

The custom converter

public class CustomLetterDayConverter : IValueConverter
{
    static HashSet<DateTime> dict = new HashSet<DateTime>();
    static CustomLetterDayConverter()
    {
        dict.Add(DateTime.Today);
        dict.Add(DateTime.Today.AddDays(1));
        dict.Add(DateTime.Today.AddDays(2));
        dict.Add(DateTime.Today.AddDays(5));
    }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        string text = null;
        if (dict.Contains((DateTime)value))
            text = null;
        else
            text = "";

        return text;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}


来源:https://stackoverflow.com/questions/53371091/displaying-dates-as-holiday-in-wpf-calendar

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!