ASP.NET GridView – OnRowDataBound vs OnRowCreated
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>
结论
我没有深入研究来详细理解这种行为,但正如我们所知……时间很短,重要的是…………大家幸福地生活在一起!!