Как определить весь диапазон дат, отображаемый в календаре ASP.NET? - PullRequest
5 голосов
/ 04 ноября 2008

Календарь ASP.NET всегда отображает даты 6 недель в сетке 7x6. Моя проблема в том, что первый день целевого месяца не обязательно появляется в первой строке ... в некоторых случаях вся первая строка отображает даты предыдущего месяца. В других случаях вся последняя строка отображает даты из следующей строки. Есть ли надежный способ запроса объекта календаря, чтобы определить 42-дневный диапазон, который будет отображаться для определенного месяца / года?

Например, рассмотрим июнь 2008 года и февраль 2009 года:

Обратите внимание, что первая неделя содержит ТОЛЬКО даты предыдущего месяца http://img371.imageshack.us/img371/2290/datesmq5.png

Я предполагаю, что календарь пытается избежать группировки всех дат «другого месяца» в верхней или нижней части сетки, и поэтому помещает первое из целевого месяца во 2-ю строку. Я ищу простой способ определить, что отображаемый диапазон для июня 2008 года - это, например, 25 мая - 5 июля.

Ответы [ 5 ]

5 голосов
/ 28 мая 2009

Я написал пару методов, чтобы помочь с этим. Просто перейдите в 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;
}
5 голосов
/ 04 ноября 2008

Глядя на общедоступных участников, доступных в элементе управления календаря ASP.NET, я не верю, что эту информацию вы можете просто получить из элемента управления календаря.

У вас есть несколько вариантов "обходных путей" к этому, хотя, хотя и не приятно .... но они будут работать.

  1. Вы можете вручную рассчитать значения первой недели
  2. Вы можете обработать событие "день рендеринга", чтобы обработать привязку отдельных дней и записать значения min / max.

Да, ни элегантно, но AFAIK - это единственный реальный вариант

Редактировать

После обсуждения в комментариях другой вариант - это модифицированная версия моего второго варианта выше. Обычно при первом вызове Day Render вызывается блок данных на следующие 42 дня, а затем вы можете просто найти в списке правильное значение дня, которое будет отображаться при будущих вызовах DayRender, избегая попадания в БД для каждого дня. Это еще одно «не элегантное» решение, но оно работает и снижает нагрузку на БД, но создает некоторые накладные расходы на стороне приложения.

Здесь будет важно определить хорошо структурированные свойства уровня страницы для хранения элементов во время событий привязки, но чтобы гарантировать, что если месяц изменился и т. Д., Он не был загружен неправильно и т. Д.

2 голосов
/ 22 октября 2009

Я просто сам разбирался в этом, и меня направили сюда. Я лично испытываю соблазн пойти на второй вариант, потому что альтернатива грязная. Версия Ронни хороша, но, к сожалению, не учитывает культуру с различными 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)));
}

К сожалению, функциональность уже есть, мы просто не можем ее получить!

2 голосов
/ 18 марта 2009

Mitchel, Работал отлично, спасибо. Началось с публичной переменной 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. Еще раз спасибо.

0 голосов
/ 28 мая 2011
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...