【问题标题】:How to determine the entire date range displayed by ASP.NET calendar?如何确定 ASP.NET 日历显示的整个日期范围?
【发布时间】:2014-12-11 07:44:07
【问题描述】:

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 日。

【问题讨论】:

    标签: asp.net calendar


    【解决方案1】:

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

    您有一些选择作为“解决方法”,虽然不是很好....但它们会起作用。

    1. 您可以手动计算第一周的值
    2. 您可以处理“day render”事件来处理各个日期的绑定,并记录最小值/最大值。

    当然两者都不优雅,但 AFAIK 是唯一真正的选择

    编辑

    在 cmets 中讨论后,另一个选项是我上面第二个选项的修改版本。基本上第一次调用 Day Render 时,获取接下来 42 天的数据块,然后您可以简单地在列表中搜索正确的日期值,以便在未来调用 DayRender 时显示,避免每天的数据库命中。这样做是另一种“不优雅”的解决方案,但它确实有效,并且减少了一些数据库负载,但在应用程序端引入了一些开销。

    在此定义结构良好的页面级属性以在绑定事件期间保存项目非常重要,但要确保如果月份发生变化等情况不会错误加载等。

    【讨论】:

    • 问题是,在从数据层获取数据之前,我需要知道将要呈现的范围,因此不能选择使用 DayRender。我可能会做#1,虽然我讨厌尝试对必要的算法进行逆向工程的想法......似乎很容易出错。不过谢谢!
    • 您是否有理由不能只在 dayrender 上调用 dB 来获取所需的确切数据?
    • @Mitchel:这将导致每天都有单独的数据库命中。我宁愿确定将显示的日期范围,然后在单个数据库调用中获取所有这些数据,不多也不少。
    • @Mitchel:除非你建议我使用 first DayRender 调用来获取整个范围的数据?我想我可以确定这是第一次渲染调用,加上 42 天,然后获取数据……它并不完美,但它有潜力。您可以添加它作为答案吗?
    • @seth:将添加该选项。在我创建日历的所有测试中,虽然我已经创建了很多,但有一件事是多个 DB 命中的开销,虽然有点影响,但为了实现的简单性,它总体上是一个可能的解决方案。
    【解决方案2】:

    我写了几个方法来帮助解决这个问题。只需传入 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;
    }
    

    【讨论】:

    【解决方案3】:

    我自己一直在研究这个,并被定向到这里。我个人很想选择选项二,因为替代方案很混乱。 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】:

      米切尔, 工作完美,谢谢。 从公共变量开始 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 日历控件的可见日期范围。再次感谢。

      【讨论】:

        【解决方案5】:

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-04-13
          • 2012-06-02
          • 1970-01-01
          • 2022-01-24
          • 2015-12-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多