我有一个动态添加到自定义 GridView 的 TemplateField。
void ITemplate.InstantiateIn(System.Web.UI.Control container)
{
switch (_templateType)
{
case ListItemType.Header:
if (this.ParentGridView.ShowDeleteHeaderImage)
{
Image hImg = new Image();
hImg.ImageUrl = this.ParentGridView.DeleteHeaderImageUrl;
hImg.AlternateText = "Mark for Deletion";
container.Controls.Add(hImg);
}
else
{
Label l = new Label();
l.Text = "Del";
container.Controls.Add(l);
}
break;
case ListItemType.Item:
container.Controls.Add(new CheckBox());
break;
case ListItemType.EditItem:
break;
case ListItemType.Footer:
QLImageButton deleteButton = new QLImageButton();
deleteButton.Settings.ImageId = "cmdQLGVDelete";
deleteButton.Settings.ImageUrl = this.ParentGridView.DeleteImageUrl;
deleteButton.CommandName = "Delete";
container.Controls.Add(deleteButton);
break;
}
}
为了响应网格命令(插入/更新/删除),调用了一个名为 GetRowControls 的方法,该方法遍历特定网格行中的列,并将其每个控件添加到字典中。
Dictionary<string, WebControl> GetRowControls(GridViewRow row)
...
rowControls.Add(ctrl.ID, (WebControl)ctrl);
...
因此,这对于以声明方式添加的模板字段和绑定控件以及以编程方式添加的动态非模板字段都适用。
但是,当控件是动态添加的 TemplateField 控件时,ctrl.ID 始终为 null,因此上面的语句会引发异常。
我用 Reflector 研究过这个问题,因为我发现当我在 VS 2005 的即时窗口中检查变量时,即 ?ctrl,ctrl.ID 会列出一个值。我已经确定这是因为在即时窗口中列出 ?ctrl 时,调用了属性 ClientID 并且 ClientID 调用了 EnsureId(),而后者又设置了 ID。
public virtual string ClientID
{
get
{
this.EnsureID();
string uniqueID = this.UniqueID;
if ((uniqueID != null) && (uniqueID.IndexOf(this.IdSeparator) >= 0))
{
return uniqueID.Replace(this.IdSeparator, '_');
}
return uniqueID;
}
}
所以我假设 ClientID、UniqueId 和 ID 都是空的——尽管如上所述,只读取前两个将触发所有设置。另请注意 NamingContainer 不为空。它已被设置。
所以解决这个问题非常简单,即检查 ctrl.ID==null,如果是这样,只需读取 ctrl.ClientID。这就是我所做的,因为从时间上讲,我真的需要继续努力。但是,如果有人不自觉地知道答案,我仍然对答案感兴趣。
为什么动态添加的 TemplateField 的子控件的 ID 值设置在与其他控件不同的时间?