You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF日历交替高亮问题:选日期后需实现3亮3暗循环高亮

解决WPF日历按起始日期后3亮3暗交替高亮的问题

嘿,我懂你要的效果了——选好起始日期(不管是DatePicker选的还是TextBox输的)之后,后面的日期得按「3天高亮、3天不高亮」的规律循环对吧?之前的代码只实现了每月固定每3天选一天,没考虑起始日期的偏移量,这就导致不符合需求了。咱们来一步步搞定:

1. 写一个日期高亮判断的转换器

首先得创建一个实现IValueConverter的类,核心逻辑是计算当前日历单元格的日期和起始日期的天数差,然后按6天一个周期(3亮+3暗)来判断是否要高亮。代码如下:

using System;
using System.Globalization;
using System.Windows.Data;

public class DateHighlightConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        // 获取当前日历单元格的日期
        if (value is DateTime cellDate && parameter is DateTime startDate)
        {
            // 只处理起始日期之后的日期
            if (cellDate.Date > startDate.Date)
            {
                // 计算天数差
                int dayDiff = (cellDate.Date - startDate.Date).Days;
                // 6天一个周期:0-2(前3天)高亮,3-5(后3天)不高亮
                if (dayDiff % 6 >= 0 && dayDiff % 6 <= 2)
                {
                    // 返回高亮的背景色,比如淡蓝色
                    return new System.Windows.Media.SolidColorBrush(System.Windows.Media.Colors.LightBlue);
                }
            }
            // 起始日期之前或者不满足高亮条件的,返回默认背景(null会用控件默认样式)
            return null;
        }
        return null;
    }

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

2. 在XAML中绑定样式与起始日期

接下来,咱们给Calendar的日期按钮设置自定义样式,把转换器用起来。首先在Resources里声明转换器,然后定义CalendarDayButton的样式,绑定它的Background到转换器,同时把ViewModel里的起始日期作为参数传进去。

假设你的ViewModel里有一个SelectedStartDate属性(实现INotifyPropertyChanged),DatePicker和TextBox都绑定到这个属性:

<Window.Resources>
    <local:DateHighlightConverter x:Key="DateHighlightConverter"/>
    <Style TargetType="CalendarDayButton">
        <Setter Property="Background" 
                Value="{Binding RelativeSource={RelativeSource Self}, 
                        Path=DataContext, 
                        Converter={StaticResource DateHighlightConverter},
                        ConverterParameter={Binding SelectedStartDate, RelativeSource={RelativeSource AncestorType=Window}}}"/>
        <!-- 可以再加个Foreground的Setter,或者调整边框,按需修改 -->
    </Style>
</Window.Resources>

<!-- 你的DatePicker和TextBox绑定到同一个起始日期属性 -->
<DatePicker SelectedDate="{Binding SelectedStartDate, Mode=TwoWay}"/>
<TextBox Text="{Binding SelectedStartDate, Mode=TwoWay, StringFormat=d}"/>

<!-- 你的Calendar控件,会自动应用上面的样式 -->
<Calendar/>

3. 处理日期输入的有效性

因为TextBox可能会输入无效日期,所以要在ViewModel的SelectedStartDate属性里做验证,避免转换器出错:

private DateTime? _selectedStartDate;
public DateTime? SelectedStartDate
{
    get => _selectedStartDate;
    set
    {
        // 如果输入无效,保留原来的值
        if (value.HasValue && value.Value != _selectedStartDate)
        {
            _selectedStartDate = value.Value.Date;
            OnPropertyChanged(nameof(SelectedStartDate));
        }
    }
}

// 记得实现INotifyPropertyChanged的OnPropertyChanged方法
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

关键细节说明

  • 转换器里的dayDiff % 6是因为3亮3暗刚好6天一个循环,余数0-2对应起始日期后的第1-3天(高亮),3-5对应第4-6天(不高亮),以此类推。
  • 一定要确保SelectedStartDate属性触发PropertyChanged,这样当用户选择或输入日期时,日历的所有日期按钮会自动重新计算样式。
  • 如果需要高亮起始日期本身,可以在转换器里加个判断:if (cellDate.Date == startDate.Date || ...),然后给起始日期单独设置样式。

这样调整之后,不管你是用DatePicker选日期,还是在TextBox里输入有效日期,日历里起始日期之后的单元格都会严格按照3天高亮、3天不高亮的规则交替显示啦!

内容的提问来源于stack exchange,提问作者Kia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:50:31