相信大家在使用calendar控件的时候觉得很麻烦,感觉它封装的实在太厉害,很多你想要的效果他很难实现。
这段时间因为工作的关系,我不得不深入的研究了一下这个控件,将里面很多的问题找到了解决方法和处理方式,现在拿出来和大家共享。
这是我现在实现的效果:
![32379_1240282155E896.jpg](http://student.csdn.net/attachment/200904/21/32379_1240282155E896.jpg)
那么现在就来介绍这样一个东西是如何一步一步的实现的(涉及到颜色布局这些我不会详细讲解,主要说的是结构上的实现,希望大家理解)。
首先来说清楚如何处理每个单元格里面是如何处理,得添加两个事件:
calendar_
DayRender
事件和
calendar_PreRender
事件。
先说
calendar_PreRender
事件吧,这个事件的作用就是在整个控件加载之前执行的事件,通过这个事件我可以为这个控件设置多语言,根据你浏览器或者web.config的配置来决定这个控件到底以什么样的语言显示
code:
protected void calNotice_PreRender(object sender, EventArgs e)
{
//setting the Calendar culture!
CultureInfo culture = new CultureInfo(this.Language);
Thread.CurrentThread.CurrentCulture = culture;
}
{
//setting the Calendar culture!
CultureInfo culture = new CultureInfo(this.Language);
Thread.CurrentThread.CurrentCulture = culture;
}
在PreRender
里面还可以完成很多事情,这里就等待大家自己去探究了。下面就开始本文的重点calendar_DayRender 事件
请大家注意,这里没有显示其他月份的日期而且本月份的背景是其他颜色的日期也是没有下划线的,在calendar里面通常都是有其他月份和下划线的,这里是如何消除的呢?
通过这段代码:
//消除背景和其他月份的日期
if (e.Day.Date.Year == time.Year && e.Day.Date.Month == time.Month)
{
e.Cell.BackColor = System.Drawing.Color.WhiteSmoke;
}
if(e.Day.IsOtherMonth)
{
e.Cell.Controls.Clear();
e.Cell.BackColor = System.Drawing.Color.Empty;
}
{
e.Cell.BackColor = System.Drawing.Color.WhiteSmoke;
}
if(e.Day.IsOtherMonth)
{
e.Cell.Controls.Clear();
e.Cell.BackColor = System.Drawing.Color.Empty;
}
//消除下划线
e.Cell.Text = string.Empty;
e.Cell.Controls.Add(new LiteralControl( e.Day.Date.Day.ToString()));
好的,背景效果这些都得到了,现在来填充单元格里面的内容了。
大家都看到了,在每个单元格里面可能出现图片,或者文字内容,要做到这些内容的来源我们首先得明白
DayRender
是如何执行的,在这个事件的头部打个断点,调试后你会发现,原来这个事件是每天都会执行一次的,那么根据这个特性我们思考的重点就在如何来处理一个单元格上来。
最初我向这个单元格里面添加其他内容都是采用添加对象的方法,例如:
Image objImage = new Image();
objImage.ImageUrl = "~/images/PCCutOff.png";
objImage.Style.Add("cursor", "hand");
e.Cell.Controls.Add(objImage);
objImage.ImageUrl = "~/images/PCCutOff.png";
objImage.Style.Add("cursor", "hand");
e.Cell.Controls.Add(objImage);
但是里面的格式是什么样的呢?我完全不能控制。但是现在我需要对这个格式进行控制以达到最后日期在最右边的现实其他在中间显示的效果。
e.Cell.Controls.Add(new LiteralControl( e.Day.Date.Day.ToString()));
通过这段code我们可以发现,这个cell是可以添加字符串的,那么我们是不是可以通过书写html代码来实现格式的控制呢?答案是肯定的。
string content = string.Empty;
content = "<table width='100%' border='0' cellspacing='0' cellpadding='0'><tr><td align='left'><span style='font-size:16px'>";
content = "<table width='100%' border='0' cellspacing='0' cellpadding='0'><tr><td align='left'><span style='font-size:16px'>";
然后在不同的位置向这个字符串中添加内容进来,最后形成完整的html代码就可以了。就是通过这样的方法来实现的。(具体的组装方法,类似动态的sql,大家自己思考一下)
OK,控件本身的工作已经完成了,那么下面我们来处理他的头部
首先先隐藏calendar控件本身的头部
然后把dropdownlist这些东西都画上去形成图上的效果,那么我们来接着添加事件了
给dropdownlist添加内容:
string language = System.Configuration.ConfigurationManager.AppSettings["Language"];//读取web.config中区域的定义
CultureInfo newci = new CultureInfo(language);
CultureInfo newci = new CultureInfo(language);
//fill month dropdown list by culture month description
for (int i = 0; i < newci.DateTimeFormat.MonthNames.Length; i++)
{
if (newci.DateTimeFormat.MonthNames[i].Length == 0)
continue;
this.ddlMonth.Items.Add(new ListItem(newci.DateTimeFormat.MonthNames[i], Convert.ToString(i + 1)));
}
然后是给dorpdownlist,左边两个右边两个linkbutton添加事件了。
事件填好好后,<< >>调用MoveYear方法,< >调用MoveMonth方法请注意,在使用者两个方法的时候,在pageLoad事件里面需要添加如下代码:
calNotice.SelectedDate = System.DateTime.Now;
calNotice.VisibleDate = System.DateTime.Now.Now;
this.calNotice.DayHeaderStyle.BackColor = System.Drawing.Color.FromArgb(255, 255, 241);
this.ddlMonth.SelectedValue = calNotice.SelectedDate.Month.ToString();
calNotice.VisibleDate = System.DateTime.Now.Now;
this.calNotice.DayHeaderStyle.BackColor = System.Drawing.Color.FromArgb(255, 255, 241);
this.ddlMonth.SelectedValue = calNotice.SelectedDate.Month.ToString();
/// <summary>
/// move calendar month by step
/// </summary>
/// <param name="step"></param>
private void MoveMonth(int step)
{
DateTime dt = this.calNotice.SelectedDate;
DateTime dtNew = dt.AddMonths(step);
calNotice.SelectedDate = dtNew;
calNotice.VisibleDate = dtNew;
this.txtYear.Text = dtNew.Year.ToString();
this.ddlMonth.SelectedValue = dtNew.Month.ToString();
}
/// move calendar month by step
/// </summary>
/// <param name="step"></param>
private void MoveMonth(int step)
{
DateTime dt = this.calNotice.SelectedDate;
DateTime dtNew = dt.AddMonths(step);
calNotice.SelectedDate = dtNew;
calNotice.VisibleDate = dtNew;
this.txtYear.Text = dtNew.Year.ToString();
this.ddlMonth.SelectedValue = dtNew.Month.ToString();
}
private void MoveYear(int count)
{
DateTime dt = this.calNotice.SelectedDate;
DateTime dtNew = dt.AddYears(count);
calNotice.SelectedDate = dtNew;
calNotice.VisibleDate = dtNew;
this.txtYear.Text = dtNew.Year.ToString();
this.ddlMonth.SelectedValue = dtNew.Month.ToString();
}
{
DateTime dt = this.calNotice.SelectedDate;
DateTime dtNew = dt.AddYears(count);
calNotice.SelectedDate = dtNew;
calNotice.VisibleDate = dtNew;
this.txtYear.Text = dtNew.Year.ToString();
this.ddlMonth.SelectedValue = dtNew.Month.ToString();
}
就这样完成了linkbutton的事件,下面是处理dropdownlist的事件:dropdownlist是调用的ChangeCalendar方法
方法如下:
private void ChangeCalendar()
{
int day = this.calNotice.SelectedDate.Day;
int year = System.DateTime.Now.Year;
try
{
year = Convert.ToInt32(this.txtYear.Text);
}
catch { }
{
int day = this.calNotice.SelectedDate.Day;
int year = System.DateTime.Now.Year;
try
{
year = Convert.ToInt32(this.txtYear.Text);
}
catch { }
int month = Convert.ToInt32(ddlMonth.SelectedValue);
DateTime dt;
try
{
dt = new DateTime(year, month, day);
}
catch
{
dt = new DateTime(year, month, DateTime.DaysInMonth(year, month));
}
calNotice.SelectedDate = dt;
calNotice.VisibleDate = dt;
}
DateTime dt;
try
{
dt = new DateTime(year, month, day);
}
catch
{
dt = new DateTime(year, month, DateTime.DaysInMonth(year, month));
}
calNotice.SelectedDate = dt;
calNotice.VisibleDate = dt;
}
OK,最后就只有一个文本框(txtYear)的回车后时间跳转这个事件了,我这里就不在写了。留给大家做个思考吧,不过有一个思路可以提供给大家,设置一个隐藏的button,你在文本框中回车后,就当是点击了这个button,在回发到服务器端响应这个事件就OK了。
最后一段代码了:
this.calNotice.Attributes.Add("title", string.Empty);//消除calendar控件中默认的title属性