65.9K
CodeProject 正在变化。 阅读更多。
Home

ASP.NET GridView – OnRowDataBound vs OnRowCreated

starIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

1.00/5 (1投票)

2015年1月11日

CPOL

2分钟阅读

viewsIcon

8973

ASP.NET GridView – OnRowDataBound vs OnRowCreated

今天早上,我在创建一个简单的 ASP.NET 页面时,与一个看似行为奇怪的 GridView 斗争了几个小时。

问题描述

我遇到的问题似乎是客户端控件的“ID”属性设置错误。通常,ASP.NET 引擎(在 4.0 版本之前)会完全负责更改 ID 以避免重复,从而确保它们始终是唯一的。特别是对于 GridView 而言,如果我们插入一个 ID = “txtSelectedValue” 的控件,并且该控件在网格的每一行中重复出现,那么它的 ClientID 将类似于

gridTest1_GridView1_ctl02_txtSelectedValue

今天早上,我花了一些时间弄清楚为什么控件反而以这种方式生成

<input id="txtSelectedValue" type="text" name="txtSelectedValue" />

代码描述

GridView 包含一个带有 ComboBox 的列,该列用于运行一个 JavaScript 函数来选择一个值。
为了更好地理解,我们立即详细查看代码

<Columns>
    <asp:TemplateField>
        <ItemTemplate>
            <asp:TextBox runat="server" ID="txtSelectedValue" Text="" />
        </ItemTemplate>
    </asp:TemplateField>
    <asp:TemplateField>
        <ItemTemplate>
            <asp:DropDownList runat="server" ID="ddlChoice">
                <asp:ListItem Text="--" />
                <asp:ListItem Text="text1" />
                <asp:ListItem Text="text2" />
                <asp:ListItem Text="text3" />
                <asp:ListItem Text="text4" />
            </asp:DropDownList>
        </ItemTemplate>
    </asp:TemplateField>
</Columns>

这是 JavaScript 函数

function selectChoice(ddl, textboxID) {
    var chosenoption = ddl.options[ddl.selectedIndex];
    if (chosenoption.value != 'nothing') {
        document.getElementById(textboxID).value = chosenoption.value;
    }
}

想要以编程方式将 JavaScript 函数添加到 DropDownList,我选择对 OnRowCreated 网格事件进行操作,如下所示

protected void GridView1_RowCreated(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        DropDownList ddlChoice = e.Row.FindControl("ddlChoice") as DropDownList;
        TextBox txtSelectedValue = e.Row.FindControl("txtSelectedValue") as TextBox;

        string jScript = "selectChoice(this, '{0}');";
        ddlChoice.Attributes.Add("onchange", string.Format(jScript, txtSelectedValue.ClientID));
    }
}

这里显示的示例可能实用意义不大,但在日常需求中,我们可能会遇到类似的情况。

如代码所示,更改 ComboBox 的值时,我们通过 <select> 控件的 onchange 事件在客户端操作,将值复制到另一个 HTML 控件中,从而避免了 aspx 页面的不必要的 PostBack,并避免了请求和 ASP.NET 引擎的代码执行。

拥有一组所有 ID 相同的控件,当然 JavaScript 函数会返回错误到以下行

document.getElementById(textboxID).value = chosenoption.value;

因为 getElementById 方法返回具有指定 id 的第一个 HTML 控件,从而破坏了整个实用函数。
这是错误的行

ddlChoice.Attributes.Add("onchange", string.Format(jScript, txtSelectedValue.ClientID));

可能,我想的是,ASP.NET 引擎此时没有创建唯一的 ID,并且参考控件的 ClientID 属性,可能,我又想了,ASP.NET 引擎决定保留静态 ID。事实上,仅仅注释掉上面的行,一切都正常工作。

解决方案

那么,我们如何将 TextBox 控件的 ID 发送到 JavaScript 函数?

参考我仍然在工作的几个神经元,我似乎记得 RowCreated 事件在 RowDataBound 之前引发,所以我认为推迟使用 ClientID 属性,我可能会解决这个问题。

通过这样做,只需将 OnRowCreated 委托中编写的代码移动到 OnRowDataBound 委托中,即可获得所需的结果。
这是在这种情况下生成的代码

<tr>
    <td>
        <input name="gridTest1$GridView1$ctl03$txtSelectedValue" type="text" 
         id="gridTest1_GridView1_ctl03_txtSelectedValue" />
    </td>
    <td>
        <select name="gridTest1$GridView1$ctl03$ddlChoice" 
         id="gridTest1_GridView1_ctl03_ddlChoice" 
         onchange="selectChoice(this, 'gridTest1_GridView1_ctl03_txtSelectedValue');">
            <option value="--">--</option>
            <option value="text1">text1</option>
            <option value="text2">text2</option>
            <option value="text3">text3</option>
            <option value="text4">text4</option>
        </select>
    </td>
</tr>

结论

我没有深入研究来详细理解这种行为,但正如我们所知……时间很短,重要的是…………大家幸福地生活在一起!!

© . All rights reserved.