DateTimePicker 应监听 ValueChanged 事件获取最新值,避免在 Click 中读取;MonthCalendar 需订阅 DateSelected 事件,用 e.Start 获取准确选中日期;两者均通过 MinDate/MaxDate 限制范围。

DateTimePicker 选完日期后怎么立刻拿到值
控件的 Value 属性就是当前选中的 DateTime,但它只在用户手动点选、键盘输入完成(比如按回车或失去焦点)后才更新。如果在 ValueChanged 事件里直接读 Value,一般没问题;但若在 Click 或 MouseUp 里读,可能拿到旧值——因为事件触发时机早于内部状态同步。
实操建议:
- 优先监听
ValueChanged事件,这是最稳妥的时机 - 避免在
Click中读Value,尤其当用户用键盘上下键调整年份时,Click根本不会触发 - 如果必须在按钮点击时取值,直接读
dateTimePicker1.Value即可,无需额外判断 -
Format属性(如DateTimePickerFormat.Short)只影响显示,不影响Value的实际值
MonthCalendar 双击选中日期后怎么捕获
MonthCalendar 没有类似 ValueChanged 的自动通知机制,它不维护“当前选中日期”的概念,而是管理一个日期范围(SelectionRange)。双击某天,会把该天设为 SelectionRange.Start 和 SelectionRange.End(即单日范围),但控件本身不抛事件。
实操建议:
- 必须手动订阅
DateSelected事件(不是DateChanged)——只有用户点击或双击日期时才触发 -
DateSelected的事件参数e.Start就是选中的那一天,类型是DateTime,直接用 - 别依赖
SelectionRange的实时读取,它可能滞后;事件里的e.Start才是最准的 - 如果用户拖选多日,
e.Start和e.End才有意义;单击/双击时二者相等
两个控件怎么限制可选日期范围
都支持设置最小/最大日期,但行为细节不同:DateTimePicker 在超出范围时会自动“卡”在边界上;MonthCalendar 则直接禁用不可选日期(灰显),且无法滚动到边界外。
实操建议:
- DateTimePicker 设置
MinDate和MaxDate即可,注意它们必须满足MinDate ,否则运行时报 <code>ArgumentOutOfRangeException - MonthCalendar 同样用
MinDate/MaxDate,但它的MaxDate不能晚于DateTime.MaxValue.Date(即不能带时间部分),否则初始化就崩 - 如果想禁止选择今天之后的日期,统一用
DateTime.Today赋值给MaxDate,别用DateTime.Now(含时分秒易出错) - 设置范围后,DateTimePicker 的下拉日历仍可能显示灰色禁用日期;MonthCalendar 则整个区域不可滚动过去
为什么 DateTimePicker 显示中文星期但 MonthCalendar 不显示
这是 WinForms 渲染逻辑差异导致的:DateTimePicker 的下拉日历由系统原生控件渲染,自动跟随系统区域设置(包括星期名称);而 MonthCalendar 是 .NET 自绘控件,其星期标题默认硬编码为英文(Sun–Sat),不读系统本地化。
实操建议:
- 无法通过属性一键改成中文星期,
MonthCalendar没有Format或Language相关属性 - 真要改,只能重写
OnPaint或用 P/Invoke 替换系统消息,成本高、不稳定,不推荐 - 日常开发中,接受它的英文星期头——用户能看懂日期数字,且点击操作不受影响
- 如果产品强制要求本地化界面,建议直接换第三方日历控件,或用
DateTimePicker+ 自定义弹出逻辑替代
最常被忽略的一点:两个控件的 Value 和 SelectionRange 都是本地时间(DateTimeKind.Local),不做时区转换。如果业务涉及跨时区存储,得手动调用 ToUniversalTime() 或 SpecifyKind(),否则数据库存的可能是错的。


















