2009-04-01 10 views
1

私はカスタムGridViewに動的に追加されたTemplateFieldを持っています。グリッドコマンドに応答してプログラムで追加されたTemplateFieldのコントロールのIDプロパティが設定されるのはいつですか?

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と呼ばれる方法は、特定gridrowの列を通っている反復と呼ばれ、辞書にそのコントロールのそれぞれを追加しています。

Dictionary<string, WebControl> GetRowControls(GridViewRow row) 
... 

rowControls.Add(ctrl.ID, (WebControl)ctrl); 

... 

これは、テンプレートフィールドとバインドコントロールの両方が宣言的に追加され、ダイナミック非テンプレートフィールドがプログラマチックに追加されていても問題ありません。

ただし、コントロールが動的に追加されたTemplateFieldコントロールの場合、ctrl.IDは常にnullなので、上記のステートメントは例外をスローします。

私はVS 2005の直接ウィンドウの変数、つまり?ctrlを調べると、ctrl.IDが値をリストすることに気づいたので、これをReflectorで調べました。私はそれ以来、これは、即時ウィンドウに?ctrlをリストするとproprty 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; 
    } 
} 

だから私はクライアントID、ユニークIDとIDがすべてNULLであることを仮定している - 上記のようにちょうど最初の二つの読み取りが設定するすべての引き金となるでしょうが。 NamingContainerがnullでないことにも注意してください。設定されています。

したがって、この回避策は非常に簡単です。つまり、ctrl.ID == nullを確認し、そうであればctrl.ClientIDを読み取ります。そして、それは時間が賢明なので私がやったことです。私は本当にぞっとする必要があります。しかし、誰もが頭の上からそれを知っているなら、私はまだ答えに興味があります。

なぜ動的に追加されたTemplateFieldの子コントロールのID値が、他のコントロールとは異なる時間に設定されていますか?

+0

完全に運ばれていますスティックの間違った端で離れて、すべての最も明白な答えを完全に逃した。受諾された回答を参照してください。 – rism

+0

私はそれが良い質問だと思った。 20年近くのプログラミングで、一見最も簡単な問題がトラブルシューティングに最も長くかかることがよくあります。 – Ruslan

+0

@Ruslan - 釈放してくれてありがとうございますが、私はまだまだ馬鹿だと感じています。それは答えが事実上問題になっている時代の一つです。;)良いニュースは、リフレクターで徹底的に掘り下げながら、いくつかのことを学びました。 – rism

答えて

2

異なる動作をしているわけではありませんが、ほとんどの場合、コントロールを宣言的に追加するとすぐにIDを設定します。 (それはIDがいっぱいになるだろうので、そのクライアントIDを表示しないように注意してください)ページにノーとIDとラベルを追加してみてくださいとコントロールコレクションを参照し、そのIDをチェックし、それはnullになります。

<asp:Label runat="server">something</asp:Label> 

も注意してくださいあなたがそれを実行するとIDなしのスパンが得られるということです。

+0

答えはとてもぼんやりとしています。私は愚かな4人が第1位で質問をしたと感じます。どのように私はcontainer.Controls.Add(新しいCheckBox())の意味を見ることができませんでした。私の防衛では、新しい「健康蹴り」のために、私は月曜日にカフェインを2回飲むのを愚かに決めたことを指摘したいと思います;) – rism

2

フレディが正しいです。

お客様は、InstantiateInメソッド内にIDを設定する責任があります。 ClientIDが特に指定されていない場合は、ClientIDが自動的に生成されます。

宣言型コントロールは、ページのコンパイル時にページビルダによって割り当てられたIDを取得します。 "Temporary ASP.NET Filesフォルダ"で生成されたtemp .csファイルの1つを見ると、次のようなものが見つかりました(プラグマが破棄されました)。

//creating a template field, where CopiledBindableTemplateBuilder is the ITemplate 
//and its InstantiateIn = @__BuildControl__control9 
@__ctrl.ItemTemplate = new System.Web.UI.CompiledBindableTemplateBuilder(
    new System.Web.UI.BuildTemplateMethod([email protected]__BuildControl__control9), 
    new System.Web.UI.ExtractTemplateValuesMethod([email protected]__ExtractValues__control9)); 

//and @__BuildControl__control9 calling @__BuildControlButton1 
private global::System.Web.UI.WebControls.Button @__BuildControlButton1() 
{ 
    global::System.Web.UI.WebControls.Button @__ctrl; 

    @__ctrl = new global::System.Web.UI.WebControls.Button(); 
    this.Button1 = @__ctrl; 
    @__ctrl.ApplyStyleSheetSkin(this); 
    @__ctrl.ID = "Button1"; //<-- here it gets an ID 
    @__ctrl.Text = "Button"; 
    return @__ctrl; 
} 
関連する問題