【问题标题】:On how to do postbacks manually, passing objects and raising events in ASP.NET user controls关于如何手动回发、在 ASP.NET 用户控件中传递对象和引发事件
【发布时间】:2011-05-05 15:07:37
【问题描述】:

我正在尝试创建一个自定义日历作为 ASP.NET 4 用户控件来做许多复杂的事情(我没有在网上找到任何适合我需要的东西)。

我设法创建了日历、传递现有事件、处理多种事件类型等等。

我不能做的是,当用户点击某一天时,传递到包含用户控件的页面DateTime 并点击该天。

我的问题是我的用户控件中没有 Web 控件(如 LinkButtons),日历是 <table />,每天都是 <td />,所以当用户点击<td />

我尝试在网络上阅读资料,但每篇教程和博客文章都是关于通过 Web 控件进行回发,而不是手动进行。

我需要了解的主要内容是:

  1. 如何将DateTime 与回发一起传递(如果这样做是正确的)? ClientScriptManager.GetPostBackEventReference 方法需要 String 作为其第二个参数,而不是对象。

  2. 如何实现类似于DropDownListOnSelectedIndexChanged 事件所暴露的行为?我的意思是,当用户点击一天的<td /> 时,我的用户控件之类的东西声明了一个事件DayClicked,我在实现该控件的页面中使用了该事件。

在回答时请注意,我不擅长使用事件和委托(这些东西对我来说是某种恶魔般的诡计)。

这里是codez

这是我现在拥有的一个简短示例(没有我需要但与实现目标无关的所有东西)。

Example.ascx

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="Example.ascx.cs" Inherits="ExampleControl" %>

<asp:PlaceHolder ID="Content" runat="server" />

Example.ascx.cs

using System;
using System.Drawing;
using System.Globalization;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class ExampleControl : UserControl
{
    public Int32 Year { get; set; }

    public Int32 Month { get; set; }

    protected void Page_Load(Object sender, EventArgs e)
    {
        // If the year has not been set.
        if (this.Year == 0)
        {
            // Set the year to the current year.
            this.Year = DateTime.Today.Year;
        }

        // If the month has not been set.
        if (this.Month == 0)
        {
            // Set the month to the current month.
            this.Month = DateTime.Today.Month;
        }

        // Create the calendar table.
        Table calendar = new Table();

        // Display grid.
        calendar.GridLines = GridLines.Both;

        // Create the calendar header (a row with the name of the days).
        TableRow calendarHeader = new TableRow();

        // Place the header in thead instead of tbody.
        calendarHeader.TableSection = TableRowSection.TableHeader;

        // Add the days of the week.
        for (Int32 dayOfWeek = 0; dayOfWeek < 7; dayOfWeek++)
        {
            // Create the cell for the day.
            TableCell dayHeader = new TableCell();

            // Set the name of the day using the current UI culture.
            dayHeader.Text = CultureInfo.CurrentUICulture.DateTimeFormat.GetAbbreviatedDayName((DayOfWeek) dayOfWeek);

            // Add the day to the header.
            calendarHeader.Cells.Add(dayHeader);
        }

        // Add the header to the calendar.
        calendar.Rows.Add(calendarHeader);

        // Create the row for the first week.
        TableRow weekRow = new TableRow();

        // Add the days of the month.
        for (DateTime day = new DateTime(this.Year, this.Month, 1); day.Year == this.Year && day.Month == this.Month; day = day.AddDays(1))
        {
            // If it's the first day of the month.
            if (day.Day == 1)
            {
                // Place enough spacers to have the first day under the right day of the week.
                for (Int32 spacer = 0; spacer < (Int32) day.DayOfWeek; spacer++)
                {
                    // Add the spacer to the week.
                    weekRow.Cells.Add(new TableCell());
                }
            }

            // If it's a new week.
            if (day.Day != 1 && day.DayOfWeek == DayOfWeek.Sunday)
            {
                // Add the previous week to the calendar.
                calendar.Rows.Add(weekRow);

                // Create a new row for the new week.
                weekRow = new TableRow();
            }

            // Create the cell for the day.
            TableCell dayCell = new TableCell();

            // When the user clicks the cell do a postback.
            dayCell.Attributes.Add("onclick", this.Page.ClientScript.GetPostBackEventReference(this, "DayClicked"));

            // Display the day of the month.
            dayCell.Text = Convert.ToString(day.Day);

            // Add the day to the week.
            weekRow.Cells.Add(dayCell);

            // If it's the last day of the month.
            if (day.Day == DateTime.DaysInMonth(this.Year, this.Month))
            {
                // Place enough spacers to fill up the week.
                for (Int32 spacer = (Int32) day.DayOfWeek; spacer < 6; spacer++)
                {
                    // Add the spacer to the week.
                    weekRow.Cells.Add(new TableCell());
                }
            }
        }

        // Add the last week to the calendar.
        calendar.Rows.Add(weekRow);

        // Add the calendar to the control.
        this.Content.Controls.Add(calendar);
    }
}

Example.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Example.aspx.cs" Inherits="ExamplePage" %>
<%@ Register Src="~/Example.ascx" TagPrefix="ex" TagName="Calendar" %>

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title>Example</title>
    </head>
    <body>
        <form runat="server">
            <asp:ScriptManager ID="ScriptManager" runat="server" />
            <h1>Example</h1>
            <asp:UpdatePanel ID="UpdatePanel" runat="server">
                <ContentTemplate>
                    <ex:Calendar ID="Calendar" Year="2011" Month="3" runat="server" />
                </ContentTemplate>
            </asp:UpdatePanel>
        </form>
    </body>
</html>

Example.aspx.cs

using System;
using System.Web.UI;

public partial class ExamplePage : Page
{
    protected void Page_Load(Object sender, EventArgs e)
    {
    }
}

【问题讨论】:

    标签: asp.net user-controls event-handling postback


    【解决方案1】:

    一种选择是让客户端脚本在调用代码回发之前使用单击的日期更新隐藏字段。然后,您将能够从服务器上的隐藏字段中获取值。

    使用这种方法,您不会错过在回发参数中单击的那一天。因此,您可以在没有自定义参数的情况下调用 GetPostBackEventReference。

    就个人而言,我会选择将其创建为自定义服务器控件而不是用户控件。你可以实现IPostBackDataHandler。在 LoadPostData 方法中,如果隐藏字段的值发生更改,您将返回 True,这将触发 .net 调用 RaisePostDataChangedEvent 方法,您将使用引发更改事件的方法进行编码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多