カスタム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であるため、上記のステートメントは例外をスローします。
リフレクターでこれを調べたのは、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はすべてnullであると想定しています。ただし、上記のように、最初の2つを読み取るだけで、すべてが設定されます。また、NamingContainerはnullではないことに注意してください。設定されています。
したがって、これを回避する方法は非常に簡単です。つまり、ctrl.ID == nullを確認し、その場合はctrl.ClientIDを読み取ります。そして、それは私がやったことです。なぜなら、時間的には本当にうごめく必要があるからです。しかし、誰かが頭のてっぺんからそれを知っているなら、私はまだ答えに興味があります。
動的に追加されたTemplateFieldの子コントロールのID値が、他のコントロールのID値とは異なる時間に設定されるのはなぜですか?