none
動的にテンプレート列を作成後、DataTableに関連付け RRS feed

  • 質問

  • たびたびお世話になっております。
    ASP.NET 2.0  VS2005 C# を使用しております。
    GridViewのテンプレート列を動的に作成しようとしています。


    ---------------------------------------------------------------
    以下のDataTableをGridViewにバインドしています。

    public class SampleDataTable : System.Data.DataTable
    {
     public SampleDataTable()
     {
      this.Columns.Add( new DataColumn( "xxx" ) );
      this.Columns.Add( new DataColumn( "yyy" ) );

      DataRow row;

      row = this.NewRow();
      row[ "xxx" ] = "1";
      row[ "yyy" ] = "2";
      this.Rows.Add( row );

      row = this.NewRow();
      row[ "xxx" ] = "2";
      row[ "yyy" ] = "1";
      this.Rows.Add( row );
     }
    }

    ---------------------------------------------------------------
    以下の2列をテンプレート列として使用します。


    public class XXXColumnTemplate : System.Web.UI.ITemplate
    {
     public void InstantiateIn( System.Web.UI.Control container )
     {
      Label label = new Label();
      label.Text = "<%# Bind(\"xxx\") %>";
      container.Controls.Add( label );
     }
    }

    public class YYYColumnTemplate : System.Web.UI.ITemplate
    {
     public void InstantiateIn( System.Web.UI.Control container )
     {
      Label label = new Label();
      label.Text = "<%# Bind(\"yyy\") %>";
      container.Controls.Add( label );
     }
    }


    ---------------------------------------------------------------
    バインドは以下のように行ないました。

    TemplateField templateField;

    templateField = new TemplateField();
    templateField.HeaderText = "xxx";
    templateField.ItemTemplate = new XXXColumnTemplate();
    sampleGridView.Columns.Add( templateField );

    templateField = new TemplateField();
    templateField.HeaderText = "yyy";
    templateField.ItemTemplate = new YYYColumnTemplate();
    sampleGridView.Columns.Add( templateField );

    // データソースをバインド
    sampleGridView.AutoGenerateColumns = false;
    sampleGridView.DataSource = new SampleDataTable();
    sampleGridView.DataBind();

     

    GridViewの表示が以下のようになることを想定していました。
    -------
    xxx|yyy
    -------
     1 | 2
    -------
     2 | 1
    -------


    ところが結果は以下の通り、DataTableの列とテンプレート列が関連付いていないようです。
    -------
    xxx|yyy
    -------

     

    ---------------------------------------------------------------
    以下の通り、aspxファイルで静的にテンプレート列を定義した場合はうまく表示されました。
    これと同じ事を動的にやりたいのですが、どのように書けばよろしいでしょうか。
    宜しくお願い致します。

    <asp:GridView>
     <Columns>
      <asp:TemplateField HeaderText="xxx" >
       <ItemTemplate>
        <asp:Label ID="lblXXX" runat="server" Text='<%# Bind("xxx") %>'></asp:Label>
       </ItemTemplate>
      </asp:TemplateField>
      <asp:TemplateField HeaderText="yyy" >
       <ItemTemplate>
        <asp:Label ID="lblYYY" runat="server" Text='<%# Bind("yyy") %>'></asp:Label>
       </ItemTemplate>
      </asp:TemplateField>
     </Columns>
    </asp:GridView>


     

    2006年12月7日 11:31

回答

  • public void InstantiateIn( System.Web.UI.Control container )
     {
      Label label = new Label();
      label.Text = "<%# Bind(\"xxx\") %>";
      container.Controls.Add( label );
     }

    がおかしいです。データバインド式はコード内では使用することができません。HTMLのソースには、<%# Bind(\"xxx\") %>がそのまま表示されているはずです。実際には以下のようになります。

    public class XXXColumnTemplate : System.Web.UI.ITemplate

    {

        public void InstantiateIn(System.Web.UI.Control container)

        {

            //Label label = new Label();

            //label.Text = "<%# Bind(\"xxx\") %>";

            //container.Controls.Add(label);

     

            Label label = new Label();

            label.DataBinding += new EventHandler(this.OnDataBinding);

            container.Controls.Add(label);

        }

     

        public void OnDataBinding(object sender, EventArgs e)

        {

            Label label = (Label)sender;

            GridViewRow container = (GridViewRow)label.NamingContainer;

            label.Text = ((DataRowView)container.DataItem)["xxx"].ToString();

        }

    }

    Labelでもいいんですが、通常はLiteralControlが使われます。また、XXXColumnTemplateとYYYColumnTemplateは一つのクラスにまとめられます。違うのはカラム名だけですので。

    2006年12月8日 1:48
    モデレータ

すべての返信

  • public void InstantiateIn( System.Web.UI.Control container )
     {
      Label label = new Label();
      label.Text = "<%# Bind(\"xxx\") %>";
      container.Controls.Add( label );
     }

    がおかしいです。データバインド式はコード内では使用することができません。HTMLのソースには、<%# Bind(\"xxx\") %>がそのまま表示されているはずです。実際には以下のようになります。

    public class XXXColumnTemplate : System.Web.UI.ITemplate

    {

        public void InstantiateIn(System.Web.UI.Control container)

        {

            //Label label = new Label();

            //label.Text = "<%# Bind(\"xxx\") %>";

            //container.Controls.Add(label);

     

            Label label = new Label();

            label.DataBinding += new EventHandler(this.OnDataBinding);

            container.Controls.Add(label);

        }

     

        public void OnDataBinding(object sender, EventArgs e)

        {

            Label label = (Label)sender;

            GridViewRow container = (GridViewRow)label.NamingContainer;

            label.Text = ((DataRowView)container.DataItem)["xxx"].ToString();

        }

    }

    Labelでもいいんですが、通常はLiteralControlが使われます。また、XXXColumnTemplateとYYYColumnTemplateは一つのクラスにまとめられます。違うのはカラム名だけですので。

    2006年12月8日 1:48
    モデレータ
  • やはりデータバインド式はコード内では使えないんですね。ご教授いただいた方法で解決できました。ありがとうございました。
    2006年12月9日 6:30
  • ありがとうございます!すばらしい

    2014年4月10日 6:14