XAML 在wpf中更改日历日期按钮的背景颜色?

swvgeqrz  于 2023-09-28  发布在  其他
关注(0)|答案(1)|浏览(117)

我正在尝试更改wpf日历控件中给定日期的背景色
给定的日期在
但是当我尝试选择日期并更改颜色时,它会更改每个月该天的颜色,而不是我需要更改该月该日期的颜色
HashSet突出显示日期
目前看起来

2023-08-24 00:00:00
2023-08-28 00:00:00
2023-08-29 00:00:00
2023-08-30 00:00:00

我尝试根据以下代码更改颜色:

private void PrintAllCalendarDates(DependencyObject depObj, HashSet<DateTime> highlightedDates)
        {

            for (int month = 1; month <= 12; month++)
            {
                // Set the displayed month in the calendar
                customCalendar.DisplayDate = new DateTime(customCalendar.DisplayDate.Year, month, 1);

                // Wait for the calendar to update (you may need to handle the Loaded event)
                customCalendar.UpdateLayout();

                // Get the PART_MonthView for the current month
                DependencyObject monthView = GetMonthView(depObj, month);

                if (monthView == null)
                {
                    // Month view not found, continue to the next month
                    continue;
                }

                // This is a CalendarButton for a specific month, so let's get its CalendarDayButtons
                int monthCalendarChildrenCount = VisualTreeHelper.GetChildrenCount(monthView);

                for (int j = 0; j < monthCalendarChildrenCount; j++)
                {
                    DependencyObject monthChild = VisualTreeHelper.GetChild(monthView, j);
                    if (monthChild is CalendarDayButton calendarDayButton)
                    {

                        foreach (DateTime datehash in highlightedDates)
                        {
                            // You can access each date in the HashSet here
                            //Debug.WriteLine(datehash.ToString());
                        }
                        //if (highlightedDates.Any(d => d.Year == date.Year && d.Month == date.Month && d.Day == date.Day))
                        //{
                        //    // Change the background color to red
                        //    calendarDayButton.Background = Brushes.Red;
                        //}

                        DateTime date = (DateTime)calendarDayButton.DataContext;
                        //if (highlightedDates.Contains(date.Date))
                        //{
                        //    foreach (var highlightedDate in highlightedDates)
                        //    {
                        //        //if (date.Month == highlightedDate.Month && date.Year == highlightedDate.Year && date.Day == highlightedDate.Day)
                        //        //{
                        //        //    // Change the background color to red
                        //        //    Debug.WriteLine(date.ToString());
                        //        //    calendarDayButton.Background = Brushes.Red;
                        //        //}
                        //        if (date.Month == 8 && date.Year == 2023 && highlightedDates.Contains(date.Date))
                        //        {
                        //            // Change the background color to red
                        //            Debug.WriteLine(date.ToString());
                        //            calendarDayButton.Background = Brushes.Red;
                        //        }
                        //    }
                        //}
                        if (date.Month == 8 && date.Year == 2023)
                        {
                            if (highlightedDates.Contains(date.Date))
                            {
                                // Change the background color to red
                                Debug.WriteLine(date.ToString());
                                calendarDayButton.Background = Brushes.Red;
                            }
                            else
                            {
                                // Set the background color to its default value for dates in August
                                calendarDayButton.Background = Brushes.White; // or any other default color
                            }
                        }
                        else
                        {
                            // Set the background color to its default value for dates in other months
                            calendarDayButton.Background = Brushes.White; // or any other default color
                        }
                    }
                }
            }
        }

        private DependencyObject GetMonthView(DependencyObject depObj, int targetMonth)
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(depObj, i);

                if (child is FrameworkElement frameworkElement && frameworkElement.Name == "PART_MonthView")
                {
                    // Check if this month matches the target month
                    int month = customCalendar.DisplayDate.Month;
                    if (month == targetMonth)
                    {
                        return child;
                    }
                }

                // Recursively call the method to check child elements
                DependencyObject result = GetMonthView(child, targetMonth);
                if (result != null)
                {
                    return result; // Found the target month view
                }
            }

            return null; // Month view not found
        }

if语句工作正常,但不是只挂起月份8的背景颜色,而是更改了日历中所有月份的正确日期。
下面是calendar控件的xaml以获取更多上下文:

<Calendar x:Name="customCalendar" DisplayDate="{Binding CurrentDate}" Margin="-533,0,533,823" Grid.RowSpan="5">
                <Calendar.CalendarDayButtonStyle>
                    <Style TargetType="CalendarDayButton">
                        <Setter Property="Background" Value="Transparent" />
                    </Style>
                </Calendar.CalendarDayButtonStyle>
            </Calendar>
ppcbkaq5

ppcbkaq51#

CalendarDayButton元素被重用。你应该使用一个转换器和一个MultiBinding来设置Background的颜色,而不是通过编程方式直接修改视觉元素:

public class BackgroundConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        DateTime date = (DateTime)values[0];
        HashSet<DateTime> dates = values[1] as HashSet<DateTime>;
        return dates != null && dates.Contains(date);
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

XAML:

<Calendar x:Name="customCalendar">
    <Calendar.Resources>
        <local:BackgroundConverter x:Key="Converter" />
    </Calendar.Resources>
    <Calendar.CalendarDayButtonStyle>
        <Style TargetType="CalendarDayButton">
            <Style.Triggers>
                <DataTrigger Value="True">
                    <DataTrigger.Binding>
                        <MultiBinding Converter="{StaticResource Converter}">
                            <Binding Path="." />
                            <Binding Path="Dates" 
                                     RelativeSource="{RelativeSource AncestorType=Window}" />
                        </MultiBinding>
                    </DataTrigger.Binding>
                    <Setter Property="Background" Value="Red" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Calendar.CalendarDayButtonStyle>
</Calendar>

窗口/视图模型:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    public HashSet<DateTime> Dates { get; } = new HashSet<DateTime>()
    {
        new DateTime(2023, 08, 24),
        new DateTime(2023, 08, 28),
        new DateTime(2023, 08, 29),
        new DateTime(2023, 08, 30)
    };
}

相关问题