WinForms MonthCalendar控件完整教程
MonthCalendar是WinForms中用于日期选择的控件,支持单日/多日选择、日期范围限制及样式定制。本教程从基础功能到高级配置进行系统性讲解,结合代码示例与场景应用。
一、控件基础操作
1. 添加控件
- 拖拽添加:从工具箱→Common Controls→MonthCalendar拖拽至窗体
- 属性配置:
Name
属性:建议使用mcCalendar
前缀命名Dock
属性:可设置为Fill
实现自适应布局
2. 核心属性详解
属性 | 作用 | 示例代码 |
---|---|---|
MinDate /MaxDate | 限制可选日期范围 | mcCalendar.MinDate = new DateTime(2020, 1, 1); |
SelectionRange | 设置默认选中范围 | mcCalendar.SelectionRange = new SelectionRange(start, end); |
ShowToday | 控制"今天"按钮显示 | mcCalendar.ShowToday = false; |
CalendarDimensions | 多月显示布局 | mcCalendar.CalendarDimensions = new Size(2, 1); // 双月横向排列 |
3. 事件处理
// 单日选择事件
private void mcCalendar_DateSelected(object sender, DateRangeEventArgs e)
{
MessageBox.Show($"选择日期: {e.Start:yyyy-MM-dd}");
}
// 日期范围变更事件
private void mcCalendar_DateChanged(object sender, DateRangeEventArgs e)
{
if (e.Start == e.End)
lblDisplay.Text = $"单日选择: {e.Start:D}";
else
lblDisplay.Text = $"范围选择: {e.Start:D} 至 {e.End:D}";
}
二、高级功能实现
1. 日期高亮配置
// 静态高亮(元旦、春节等)
DateTime[] holidays = { new DateTime(2025, 1, 1), new DateTime(2025, 2, 10) };
mcCalendar.BoldedDates = holidays;
// 动态高亮(每月15日)
private void Form_Load(object sender, EventArgs e)
{
List<DateTime> monthlyDates = new List<DateTime>();
for (int i = 1; i <= 12; i++)
monthlyDates.Add(new DateTime(2025, i, 15));
mcCalendar.MonthlyBoldedDates = monthlyDates.ToArray();
}
2. 跨控件交互
// 工具栏日期选择实现
private void txtStartDate_Click(object sender, EventArgs e)
{
mcCalendar.Location = txtStartDate.PointToScreen(Point.Empty);
mcCalendar.Show();
}
private void mcCalendar_DateSelected(object sender, DateRangeEventArgs e)
{
txtStartDate.Text = e.Start.ToString("yyyy.MM.dd");
mcCalendar.Hide();
}
3. 多语言支持
// 设置首日为周一
mcCalendar.FirstDayOfWeek = DayOfWeek.Monday;
// 格式化显示
private void mcCalendar_DateChanged(object sender, DateRangeEventArgs e)
{
lblDisplay.Text = $"选择: {e.Start:yyyy年MM月dd日 dddd}"; // 显示星期名称
}
三、常见场景解决方案
1. 日期范围限制
// 限制选择范围为30天内
mcCalendar.MaxSelectionCount = 30;
// 动态调整最大可选日期
private void UpdateMaxDate()
{
mcCalendar.MaxDate = DateTime.Now.AddMonths(6); // 最大可选未来6个月
}
2. 特殊日期标记
// 添加红色背景标记
private void mcCalendar_DrawItem(object sender, DrawMonthCalendarEventArgs e)
{
if (e.Bounds.Height > 0) // 排除标题栏
{
if (e.Date.Day == 15) // 每月15日标记
{
e.Graphics.FillRectangle(Brushes.LightPink, e.Bounds);
e.Graphics.DrawString(e.Date.Day.ToString(),
e.Font,
Brushes.Red,
e.Bounds);
return;
}
}
e.DrawBackground();
e.DrawText();
}
3. 数据验证
// 验证日期有效性
private bool ValidateDateRange(DateTime start, DateTime end)
{
if (start > end)
{
errorProvider.SetError(mcCalendar, "结束日期必须晚于开始日期");
return false;
}
errorProvider.Clear();
return true;
}
四、性能优化建议
- 事件节流:对频繁触发的
DateChanged
事件添加防抖处理 - 资源释放:在窗体关闭时调用
Dispose()
释放控件资源 - 多线程处理:大数据量日期计算时使用
BackgroundWorker
五、完整示例代码
public partial class DateSelectorForm : Form
{
public DateSelectorForm()
{
InitializeComponent();
// 基础配置
mcCalendar.MinDate = DateTime.Now.AddYears(-1);
mcCalendar.MaxDate = DateTime.Now.AddYears(1);
mcCalendar.CalendarDimensions = new Size(2, 1);
// 事件绑定
mcCalendar.DateSelected += McCalendar_DateSelected;
mcCalendar.DrawItem += McCalendar_DrawItem;
// 初始化标记
InitializeBoldedDates();
}
private void InitializeBoldedDates()
{
// 节假日标记
DateTime[] holidays = {
new DateTime(2025, 1, 1), new DateTime(2025, 2, 10),
new DateTime(2025, 5, 1), new DateTime(2025, 10, 1)
};
mcCalendar.BoldedDates = holidays;
// 每月15日标记
List<DateTime> monthlyDates = new List<DateTime>();
for (int i = 1; i <= 12; i++)
monthlyDates.Add(new DateTime(2025, i, 15));
mcCalendar.MonthlyBoldedDates = monthlyDates.ToArray();
}
private void McCalendar_DateSelected(object sender, DateRangeEventArgs e)
{
if (e.Start == e.End)
lblResult.Text = $"单日选择: {e.Start:yyyy-MM-dd}";
else
lblResult.Text = $"范围选择: {e.Start:yyyy-MM-dd} 至 {e.End:yyyy-MM-dd}";
}
private void McCalendar_DrawItem(object sender, DrawMonthCalendarEventArgs e)
{
if (e.Bounds.Height > 0)
{
// 节假日红色显示
if (Array.Exists(mcCalendar.BoldedDates, d => d == e.Date))
{
e.Graphics.FillRectangle(Brushes.LightCoral, e.Bounds);
e.Graphics.DrawString(e.Date.Day.ToString(),
e.Font,
Brushes.White,
e.Bounds);
return;
}
// 每月15日蓝色显示
if (e.Date.Day == 15)
{
e.Graphics.FillRectangle(Brushes.LightBlue, e.Bounds);
e.Graphics.DrawString(e.Date.Day.ToString(),
e.Font,
Brushes.Black,
e.Bounds);
return;
}
}
e.DrawBackground();
e.DrawText();
}
}
六、注意事项
- 时区处理:涉及跨时区应用时需使用
DateTimeOffset
类型 - 无障碍支持:为视力障碍用户添加
ToolTip
控件 - 本地化适配:日期格式需根据
CultureInfo.CurrentCulture
动态调整
通过以上配置,MonthCalendar控件可满足90%以上的日期选择场景需求。对于更复杂的需求(如节假日计算),建议结合第三方库(如NodaTime)实现。