如何在使用ASP.NET日历控件时隐藏周末?

6
有时在显示日历时,需要防止周末日期和星期名称在日期标题中显示,是否可以使用 ASP.NET 日历控件 来实现此功能?
6个回答

7
由于提供了控件,没有办法在不覆盖控件的情况下完成此操作。一种方法是重写 OnDayRenderRender 方法,在将信息发送回客户端之前从输出中删除信息。
以下是控件呈现时的屏幕截图:

Example of weekday calendar

以下是一个基本的控件覆盖,演示如何从控件中删除周末天数列。
/*------------------------------------------------------------------------------
 * Author - Rob (http://stackoverflow.com/users/1185/rob)
 * -----------------------------------------------------------------------------
 * Notes
 * - This might not be the best way of doing things, so you should test it
 *   before using it in production code.
 * - This control was inspired by Mike Ellison's article on The Code Project
 *   found here: http://www.codeproject.com/aspnet/MellDataCalendar.asp
 * ---------------------------------------------------------------------------*/
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Text;
using System.IO;
using System.Xml;

namespace DataControls
{
    /// <summary>
    /// Example of a ASP.NET Calendar control that has been overriden to force
    /// the weekend columns to be hidden on demand.
    /// </summary>
    public class DataCalendar : Calendar
    {
        private bool _hideWeekend;
        private int _saturday;
        private int _sunday;

        /// <summary>Constructor</summary>
        public DataCalendar()
            : base()
        {
            // Default to showing the weekend
            this._hideWeekend = false;
            // Set the default values for Saturday and Sunday
            this.Saturday = 6;
            this.Sunday = 0;
        }

        /// <summary>
        /// Indicate if the weekend days should be shown or not, set to true
        /// if the weekend should be hidden, false otherwise. This field 
        /// defaults to false.
        /// </summary>
        public bool HideWeekend
        {
            get { return this._hideWeekend; }
            set { this._hideWeekend = value; }
        }

        /// <summary>
        /// Override the default index for Saturdays.
        /// </summary>
        /// <remarks>This option is provided for internationalization options.</remarks>
        public int Saturday 
        {
            get { return this._saturday; }
            set { this._saturday = value; }
        }


        /// <summary>
        /// Override the default index for Sundays.
        /// </summary>
        /// <remarks>This option is provided for internationalization options.</remarks>
        public int Sunday 
        {
            get { return this._sunday; }
            set { this._sunday = value; }
        }

        /// <summary>
        /// Render the day on the calendar with the information provided.
        /// </summary>
        /// <param name="cell">The cell in the table.</param>
        /// <param name="day">The calendar day information</param>
        protected override void OnDayRender(TableCell cell, CalendarDay day)
        {
            // If this is a weekend day and they should be hidden, remove
            // them from the output
            if (day.IsWeekend && this._hideWeekend)
            {
                day = null;
                cell.Visible = false;
                cell.Text = string.Empty;
            }
            // Call the base render method too
            base.OnDayRender(cell, day);
        }

        /// <summary>
        /// Render the calendar to the HTML stream provided.
        /// </summary>
        /// <param name="html">The output control stream to write to.</param>
        protected override void Render(HtmlTextWriter html)
        {
            // Setup a new HtmlTextWriter that the base class will use to render
            StringBuilder sb = new StringBuilder();
            StringWriter sw = new StringWriter(sb);
            HtmlTextWriter calendar = new HtmlTextWriter(sw);
            // Call the base Calendar's Render method allowing OnDayRender() 
            // to be executed.
            base.Render(calendar);
            // Check to see if we need to remove the weekends from the header,
            // if we do, then remove the fields and use the new verison for
            // the output. Otherwise, just use what was previously generated.
            if (this._hideWeekend && this.ShowDayHeader)
            {
                // Load the XHTML to a XML document for processing
                XmlDocument xml = new XmlDocument();
                xml.Load(new StringReader(sw.ToString()));
                // The Calendar control renders as a table, so navigate to the
                // second TR which has the day headers.
                XmlElement root = xml.DocumentElement;
                XmlNode oldNode = root.SelectNodes("/table/tr")[1];
                XmlNode sundayNode = oldNode.ChildNodes[this.Sunday];
                XmlNode saturdayNode = oldNode.ChildNodes[this.Saturday];
                XmlNode newNode = oldNode;
                newNode.RemoveChild(sundayNode);
                newNode.RemoveChild(saturdayNode);
                root.ReplaceChild(oldNode, newNode);
                // Replace the buffer
                html.WriteLine(root.OuterXml);
            }
            else
            {
                html.WriteLine(sw.ToString());
            }
        }
    }
}

1
只是一个小注释,当我实现这个功能时,日期标题从星期二到星期六。对我来说,诀窍是更改以下行:XmlNode sundayNode = oldNode.ChildNodes[0]; 为:XmlNode sundayNode = oldNode.ChildNodes[5]; 可能是因为我在英国? - Brian
@Brian - 很可能是这样,我在使用星期日作为日历第一天的美国。我没有在代码中包含任何本地化逻辑,所以这可能是我需要在某个时候处理的事情。 - rjzii
@Joel - 刚刚实现并在IE中测试了一下,可预见的是它并没有像我们希望的那样出现。工作日标题和日期单元格都以日历宽度的5/7呈现。这是由于删除了两列日期所致。我有一个解决方法(将xml中的任何“width:14%”替换为“width:20%”),并希望与其他人分享我的解决方案。我应该怎么做才能做到最好? - Brian
@Brian - 我写的原始修改只是一个示例,供大家参考,而不是完整的生产版本。你最好的选择可能是用你自己的版本回答这个问题,或者你可以在某个地方写一篇博客文章并发布链接。 - rjzii

0

正如zacharydl所建议的那样,我使用jQuery成功地隐藏了周末。我对原始代码进行了一些小改动。

 <script type="text/javascript">
   HideWeekEnd();


    function HideWeekEnd ()
    {
        $('._title').parent().attr('colspan', '7');  
        $('._dayheader:nth-last-child(1) , ._dayheader:nth-last-child(2) ', $('#<%= Calendar1.ClientID %>')).hide(); // remove last two cells from day header row
        $('._weekendday').hide(); // remove all the cells marked weekends
    }

 Sys.Application.add_init(appl_init);

        function appl_init() {
            var pgRegMgr = Sys.WebForms.PageRequestManager.getInstance();
            pgRegMgr.add_endRequest(HideWeekEnd);
        }

</script>

您需要在页面的endRequest事件中注册HideWeekEnd(),以确保在页面回传期间调用它。


0

我相信你可以处理Day Render事件并隐藏单元格或分配CSS属性使其不可见或变灰。以下是一个简单的例子,希望这可以帮到你。

protected void Calendar_DayRender(object sender, DayRenderEventArgs e)
{

  e.Cell.Visible = False;
  // or
  // e.Cell.Attributes.Add("class", "Invisible");
  // or
  // e.Cell.Attributes.Add("style", "display: none");
}

1
这只是隐藏了日期字段的内容,您仍需要进行额外的工作才能删除日期标题。 - rjzii

0

这里有另一种只使用 CSS 实现的方法:

 <style>
   .hidden,
   #Calendrier tr > th[abbr=Saturday],
   #Calendrier tr > th[abbr=Sunday] { display:none; }
   #Calendrier tr > th { text-align: center; }
 </style>

 <asp:Calendar ID="Calendar1" DayNameFormat="Full" runat="server" 
               WeekendDayStyle-CssClass="hidden" ClientIDMode="Static"  >
 </asp:Calendar>

0
如果你使用jQuery解决方案没问题的话,只需要几行代码即可:
<script type="text/javascript">
    $(document).ready(function () {
        $('._title').parent().attr('colspan', '5'); // title row initially has a colspan of seven
        $('._dayheader:first, ._dayheader:last', $('#<%= Calendar1.ClientID %>')).hide(); // remove first and last cells from day header row
        $('._weekendday').hide(); // remove all the cells marked weekends
    });
</script>

<asp:Calendar runat="server" ID="Calendar1">
    <TitleStyle CssClass="_title" />
    <DayHeaderStyle CssClass="_dayheader" />
    <WeekendDayStyle CssClass="_weekendday" />
</asp:Calendar>

以下是对此方法的一些考虑:

  • 如果 JavaScript 被禁用,客户端将看到周末。
  • 在旧版、速度较慢的浏览器中,随着 jQuery 在加载时执行,日历会有点跳动。
  • 这个解决方案可能可以直接使用 CSS 实现 :first-child
  • 如果在页面上添加了另一个日历,您需要复制 JavaScript 的中间行。这是必要的,因为我们使用了 :first 和 :last。
  • 如果页面上只有一个日历控件,您可以通过删除 jQuery 选择器的第二个参数来简化 JavaScript 的中间行:$('#<%= Calendar1.ClientID %>')

0
据我所知,你不能这样做,但是你可以尝试使用WeekendDayStyle进行实验,例如通过设置display:none来设置样式。或者,你可以创建一个继承自Calendar的自定义控件,并覆盖Render、OnDayRender或其他方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接