如何确定ASP.NET日历显示的整个日期范围?

时间:2008-11-04 18:28:39

标签: asp.net calendar

ASP.NET日历始终在7x6网格中显示6周的日期。我的问题是,目标月份的第一天不一定出现在第一行...在某些情况下,整个第一行显示上个月的日期。在其他情况下,整个最后一行显示下一行的日期。 是否有可靠的方法来查询日历对象以确定特定月/年的42天范围?

例如,考虑2008年6月和2009年2月:

Notice that the first week contains ONLY dates from prior month http://img371.imageshack.us/img371/2290/datesmq5.png

我假设日历试图避免在网格的顶部或底部聚集所有“其他月份”日期,因此将第一个目标月份放在第二行。我正在寻找一种简单的方法来确定2008年6月的显示范围是5月25日 - 7月5日。

5 个答案:

答案 0 :(得分:5)

查看ASP.NET日历控件公开的公共成员,我不相信这些信息是您可以从日历控件中获取的信息。

你有一些选择作为“变通办法”,尽管不是很好....但是它们会起作用。

  1. 您可以手动计算第一周的值
  2. 您可以处理“day render”事件来处理各个日期的绑定,并记录最小/最大值。
  3. 既不优雅,但AFAIK是唯一真正的选择

    修改

    在评论中讨论后,另一个选项是我上面第二个选项的修改版本。基本上第一次调用Day Render时,获取接下来42天的数据块,然后您只需在列表中搜索正确的日值,以便在将来调用DayRender时显示,从而避免每天的数据库命中。这样做是另一个“非优雅”的解决方案,但它可以工作,并减少了DB上的一些负担,但在应用程序方面引入了一些开销。

    在这里定义结构良好的页面级别属性以在绑定事件期间保存项目非常重要,但要确保如果一个月发生更改等,则表明未正确加载等等。

答案 1 :(得分:5)

我写了几个方法来帮助解决这个问题。只需传递Calendar.VisibleDate:

public static DateTime GetFirstDateOfMonth(DateTime date)
{
    return new DateTime(date.Year, date.Month, 1);
}

public static DateTime GetFirstDisplayedDate(DateTime date)
{
    date = GetFirstDateOfMonth(date);
    return date.DayOfWeek == DayOfWeek.Sunday ? date.AddDays(-7) : date.AddDays((int)date.DayOfWeek * -1);
}

public static List<DateTime> GetDisplayedDates(DateTime date)
{
    date = GetFirstDisplayedDate(date);

    List<DateTime> dates = new List<DateTime>();
    for (int i = 0; i < 42; i++)
    {
        dates.Add(date.AddDays(i));
    }

    return dates;
}

答案 2 :(得分:2)

米切尔, 工作得很完美,谢谢。 从公共变量开始 bool m_FirstDay = false

在day_render函数中

if(m_FirstDay == false)
{
    DateTime firstDate;
    DateTime lastDate;

    firstDate = e.Day.Date;
    lastDate = firstDate.AddDays(41);

    m_FirstDay = true;
}

然后我有了asp.net日历控件的可见日期范围。再次感谢。

答案 3 :(得分:2)

我自己一直在调查,并被引导到这里。我个人很想选择第二种选择,因为替代方案很混乱。 Ronnie的版本很不错,但不幸的是没有考虑到FirstDayOfWeeks不同的文化。

使用Reflector,我们可以看到它是如何在内部完成的:


    ...
    DateTime visibleDate = this.EffectiveVisibleDate();
    DateTime firstDay = this.FirstCalendarDay(visibleDate);
    ...

private System.Globalization.Calendar threadCalendar = 
    DateTimeFormatInfo.CurrentInfo.Calendar;

private DateTime EffectiveVisibleDate()
{
    DateTime visibleDate = this.VisibleDate;
    if (visibleDate.Equals(DateTime.MinValue))
    {
        visibleDate = this.TodaysDate;
    }
    if (this.IsMinSupportedYearMonth(visibleDate))
    {
        return this.minSupportedDate;
    }
    return this.threadCalendar.AddDays(visibleDate, 
        -(this.threadCalendar.GetDayOfMonth(visibleDate) - 1));
}


private DateTime FirstCalendarDay(DateTime visibleDate)
{
    DateTime date = visibleDate;
    if (this.IsMinSupportedYearMonth(date))
    {
        return date;
    }
    int num = ((int) 
       this.threadCalendar.GetDayOfWeek(date)) - this.NumericFirstDayOfWeek();
    if (num <= 0)
    {
        num += 7;
    }
    return this.threadCalendar.AddDays(date, -num);
}

private int NumericFirstDayOfWeek()
{
    if (this.FirstDayOfWeek != FirstDayOfWeek.Default)
    {
        return (int) this.FirstDayOfWeek;
    }
    return (int) DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek;
}

private bool IsMinSupportedYearMonth(DateTime date)
{
    return this.IsTheSameYearMonth(this.minSupportedDate, date);
}

private bool IsTheSameYearMonth(DateTime date1, DateTime date2)
{
    return (((this.threadCalendar.GetEra(date1) == 
                   this.threadCalendar.GetEra(date2)) &&
          (this.threadCalendar.GetYear(date1) == 
                   this.threadCalendar.GetYear(date2))) &&
          (this.threadCalendar.GetMonth(date1) ==
                   this.threadCalendar.GetMonth(date2)));
}

可悲的是,功能已经存在,我们无法实现它!

答案 4 :(得分:0)