Visual Basic Express 2010日历控件如何设置多组可选日期范围?
实现WinForms MonthCalendar多组可选日期范围的解决方案
你之前遇到的问题其实很典型——MonthCalendar的MinDate和MaxDate确实只能设置单个连续的可选范围,多次赋值肯定会覆盖掉之前的设置,根本没法实现多组独立的可选区间。至于你说的BlackoutDates没生效,大概率是用法没搞对,咱们一步步来理清楚怎么实现需求。
核心思路:用BlackoutDates做"排除法"
BlackoutDates的作用是标记不可选的日期,所以要实现多组可选范围,咱们反过来操作:先确定所有不允许选择的日期/区间,把它们加入黑名单,剩下的自然就是可选的多组范围了。
具体实现步骤
1. 定义你的多组允许日期范围
首先把你需要开放的可选区间整理成列表,比如你提到的两组:
' 定义允许的日期范围列表 Dim allowedRanges As New List(Of Tuple(Of DateTime, DateTime))() allowedRanges.Add(Tuple.Create(New DateTime(2019, 4, 2), DateTime.Today)) allowedRanges.Add(Tuple.Create(New DateTime(2019, 4, 12), New DateTime(2019, 4, 24)))
2. 设置全局的Min/Max范围(可选但推荐)
先把MonthCalendar的整体可选边界设为所有允许区间的最小起始和最大结束,避免用户看到完全无关的日期:
' 计算全局最小和最大日期 Dim globalMin As DateTime = allowedRanges.Min(Function(r) r.Item1) Dim globalMax As DateTime = allowedRanges.Max(Function(r) r.Item2) MonthCalendar1.MinDate = globalMin MonthCalendar1.MaxDate = globalMax
3. 批量添加不可选日期到BlackoutDates
这里分两种情况,根据你的日期范围大小选择:
情况1:日期范围小(比如几个月),直接遍历每一天
这种方法简单直观,适合小范围日期:
' 先清空之前的黑名单设置 MonthCalendar1.BlackoutDates.Clear() Dim currentDate As DateTime = globalMin While currentDate <= globalMax ' 检查当前日期是否在任意一个允许区间内 Dim isAllowed As Boolean = allowedRanges.Any(Function(r) currentDate >= r.Item1 AndAlso currentDate <= r.Item2) ' 如果不在允许区间,就加入黑名单 If Not isAllowed Then MonthCalendar1.BlackoutDates.Add(New CalendarDateRange(currentDate, currentDate)) End If currentDate = currentDate.AddDays(1) End While
情况2:日期范围大(比如几年),添加连续不可选区间
如果允许的范围跨度过大,遍历每一天效率会很低,这时候可以计算出允许区间之间的空白部分,把这些连续的空白区间直接加入黑名单:
MonthCalendar1.BlackoutDates.Clear() ' 先把允许的区间按起始日期排序 Dim sortedRanges = allowedRanges.OrderBy(Function(r) r.Item1).ToList() Dim previousEnd As DateTime = globalMin.AddDays(-1) For Each range In sortedRanges ' 检查当前区间和上一个区间之间是否有空白 If range.Item1 > previousEnd.AddDays(1) Then ' 把空白区间加入黑名单 MonthCalendar1.BlackoutDates.Add(New CalendarDateRange(previousEnd.AddDays(1), range.Item1.AddDays(-1))) End If ' 更新上一个区间的结束日期(取较大值,避免区间重叠的情况) previousEnd = Math.Max(previousEnd, range.Item2) Next ' 处理最后一个允许区间之后的日期 If previousEnd < globalMax Then MonthCalendar1.BlackoutDates.Add(New CalendarDateRange(previousEnd.AddDays(1), globalMax)) End If
为什么你之前的BlackoutDates没生效?
大概率是你搞反了逻辑——可能你把允许的日期加到了BlackoutDates里,或者没有先清空之前的黑名单设置,导致新的设置被旧的覆盖了。按照上面的方法,把不允许的日期/区间加入BlackoutDates,就能正常生效了。
最后,选中的日期存入Access数据库的逻辑和之前一样,用SQL语句插入即可,这个部分不受日期选择限制的影响。
内容的提问来源于stack exchange,提问作者LAKing
相关产品推荐
相关产品推荐

