WebSurfer's Home

トップ > Blog 1   |   ログイン
APMLフィルター

DataGrid, GridView に動的に列を追加 (2)

by WebSurfer 2021年9月21日 14:56

昔「DataGrid, GridView に動的に列を追加」という記事を書きましたが、その記事よりスマートにできる方法を見つけたので以下に書いておきます。

GridView での実行結果

先の記事ではどのようにしたかと言うと、DataGrid, GridView を構成している TableCellCollection の適切な位置に TableCell を追加するというプリミティブなやり方です。なので、列を追加するだけでもかなりコードを書かなければならないし、コントロールにデーターバインドしようとするとさらに面倒なことになります。

ところが最近になって Microsoft の Visual Studio 2008 用の MSDN ライブラリに「方法 : DataList Web サーバー コントロールのテンプレートを動的に作成する 」という記事があるのを見つけ、その方法が DataGrid, GridView にも使えることを知りました。

その MSDN ライブラリはもうネットには見つかりませんので、スクリーンショットを撮ってこの記事の下の方に貼っておきます。興味がありましたら見てください。

先の記事に書いたような TableCell を追加してなんちゃらという面倒なことをする必要はなく、TemplateColumn (DataGrid の場合) または TemplateField (GridView の場合) を生成し、それを DataGrid.Columns.Add メソッドまたは GridView.Columns.Add で追加するということで列の追加が可能です。

TemplateColumn, TemplateField の中身はユーザーコントロール (.ascx) から作成します。作成したユーザーコントロールから TemplateControl.LoadTemplate メソッドで ITemplate インターフェイスのインスタンスを生成し、当該テンプレート (ItemTemplate, AlternatingItemTemplate 等) に代入してやります。

ユーザーコントロール内に配置したコントロールには <%# Eval("Name") %> というようなデータバインド式を含めることができます。そうしておけば、静的にデータバインド式を使った場合と同様に、自動的にデータソースからデータを取得して表示されます。

具体例は以下の通りです。上の画像を表示したコードで、データソースに SQL Server のサンプルデータベース Northwind の Products テーブルを使って、その PtoductName 列と Discontinued 列を動的に追加した TemplateColumn, TemplateField に表示しています。

(1) ユーザーコントロールの作成

テンプレートの中身のコントロールを配置したユーザーコントロール (.ascx) を作成します。以下の例では CheckBox と Label をテンプレートの中身として配置しています。データバインド式を含めているところにも注目してください。

<%@ Control Language="C#" AutoEventWireup="true" 
    CodeBehind="NewTemplate.ascx.cs" 
    Inherits="WebApplication2.NewTemplate" %>

製造中止: 
<asp:CheckBox ID="CheckBox1" runat="server" 
    Checked='<%# Eval("Discontinued") %>' 
    Enabled="false" />
/ 
製品名: 
<asp:Label ID="Label1" runat="server" 
    Text='<%# Eval("ProductName") %>'>
</asp:Label>

ユーザーコントロールの名前は、ここでは NewTemplate.ascx としました。名前は任意に設定して構いませんが .aspx.cs の LoadTemplate メソッドの引数にその名前を使いますので注意してください。

(2) TemplateColumn, TemplateField の追加

.aspx.cs

DataGrid は TemplateColumn を、GridView は TemplateField を使うという違いがあり、それによる若干の違いがありますので注意してください。

using System;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace WebApplication2
{
    public partial class LoadTemplate : System.Web.UI.Page
    {
        protected void Page_Init(object sender, EventArgs e)
        {
            // DataGrid に TemplateColumn を追加
            var templateColumn = new TemplateColumn();
            templateColumn.HeaderText = "動的に追加した TemplateColumn";
            templateColumn.ItemTemplate = LoadTemplate("NewTemplate.ascx");
            DataGrid1.Columns.Add(templateColumn);

            // GridView に TemplateField を追加
            var templateField = new TemplateField();
            templateField.HeaderText = "動的に追加した TemplateField";
            templateField.ItemTemplate = LoadTemplate("NewTemplate.ascx");
            GridView1.Columns.Add(templateField);
        }
    }
}

.aspx

マスターページを使っています。ほぼ 100% デザイナで自動生成したコードで、DB の ProductID のみを表示するように作成しました。ProductName と Discontinued は上の .aspx.cs で動的に追加した列に表示します。

<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" 
    AutoEventWireup="true" CodeBehind="LoadTemplate.aspx.cs" 
    Inherits="WebApplication2.LoadTemplate" %>

<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
    
    <asp:SqlDataSource ID="SqlDataSource1" 
        runat="server" 
        ConnectionString="<%$ ConnectionStrings:NORTHWINDConnectionString %>" 
        SelectCommand="SELECT TOP 10 [ProductID], [ProductName], [Discontinued] 
                       FROM [Products]">
    </asp:SqlDataSource>

    <h3>DataGrid</h3>
    <asp:DataGrid ID="DataGrid1"
        runat="server" 
        AutoGenerateColumns="False" 
        DataSourceID="SqlDataSource1">
        <Columns>
            <asp:BoundColumn DataField="ProductID" 
                HeaderText="ProductID" />
        </Columns>
    </asp:DataGrid>

    <h3>GridView</h3>
    <asp:GridView ID="GridView1" 
        runat="server" AutoGenerateColumns="False" 
        DataKeyNames="ProductID" 
        DataSourceID="SqlDataSource1">
        <Columns>
            <asp:BoundField DataField="ProductID" 
                HeaderText="ProductID" 
                InsertVisible="False" ReadOnly="True" 
                SortExpression="ProductID" />
        </Columns>
    </asp:GridView>
</asp:Content>

最後に、上にも書きましたが、参考にした Visual Stidio 2008 の MSDN ライブラリのスクリーンショットを下に貼っておきます。

MSDN ライブラリ

Tags: , , ,

ASP.NET

数字と他の文字混在の列のソート

by WebSurfer 2021年5月22日 19:44

以下のように数字とその他の文字が混在している列がある SQL Server のテーブルを ASP.NET Web Forms アプリの GridView に表示し、数字だけの行とその他の行を分けてソートする方法を書きます。

SQL Server のテーブル

元の話は Teratail のスレッド「gridviewで数値と文字列が混在している際に数値の大小順に並べ替えたい」のものです。それは Access を使った場合ですが、SQL Server で同様なことを行います。

昇順降順のソートだけでなく、GridView + SqlDataSource に組み込まれている選択、ページング、データの編集・更新機能も働くようにするのが条件です。

例えば、上の画像のテーブルの Name フィールドを、数字だけの行とその他の行を分けて昇順にソートするには、ISNUMERIC (Transact-SQL)CAST (Transact-SQL) を ORDER BY 句に使って以下のようにすることで可能です。

ORDER BY によるソート

まず、ORDER BY ISNUMERIC([Name]) DESC で数字だけの行が先に来るように並び替え(数字の場合は 1、それ以外は 0 になるので DESC を付与しています)、その結果を CAST WHEN ... END ASC で数字の場合は FLOAT に変換しそれ以外は 0 にしてから昇順 (ASC) に並べ替え、さらにその結果を [Name] ASC で普通に文字列として昇順 (ASC) に並べ替えを行っています。

(上に紹介した ISNUMERIC のドキュメントの説明に "有効な数値データ型は次のとおりです・・・" とあって、その中に文字列型はありません。しかし、上の画像の通り、自分の開発環境にある SQL Server 2012 で試した限りは nvarchar でも判定してくれました。公式ドキュメントに nvarchar でもよいと書いてないのは不安要素ではありますが)

GridView + SqlDataSource を使ってテーブルのレコード一覧を表示する場合、単純に文字列としてソーティングを行うなら GridView の AllowPaging プロパティを true に設定するだけで、GridView + SqlDataSource に組み込まれた機能を使って一行もコードを書かずにソート機能を実装可能です。

ちなみに、GridView + SqlDataSource に備わっているデフォルトのソート機能というのは以下のようになっています。

  1. GridView の AllowPaging プロパティを true に設定するとヘッダがリンクボタンになる。
  2. リンクボタンのクリックによってポストバックが起こる。
  3. サーバー側ではそれを受けて SQL Server から SqlDataSource 経由でデータを取得。(その時、SqlDataSource の SelectCommand プロパティに設定した SELECT クエリがそのまま SQL Server に発行されます。ORDER BY 句を付与して発行されるわけではありません。リンクボタンをクリックするたび毎回ポストバックが発生し、その都度 SQL Server にクエリが発行される点にも注意してください)
  4. 取得したデータから DataView を作って、その Sort プロパティにクリックされたリンクボタンのある列の SortExpression を設定。(SortExpression はデフォルトではその列の列名すなわち DataView の列名と同じになっています)
  5. それによりソートされた結果を GirdView に表示する。
  6. 同じリンクボタンを再度クリックすると、上記 2 ~ 4 と同じプロセスが実行されるが、昇順降順が切り替わる。(上記 4 で ASC, DESC を切り替えて付与しているようです)

なので、例えば、上の 2 つ目の画像の ORDER BY 句つき SELECT クエリを SqlDataSource の SelectCommand プロパティに設定すると、初期画面ではレコード一覧は 2 つ目の画像のとおり表示されますが、ヘッダのリンボタンをクリックすると上の 4 の結果、すなわち単純に文字列としてソーティングした結果が表示されます。

それでは要件を満足できず、全ての列のヘッダのリンクボタンのクリックで上の 2 つ目の画像のように数字だけの行とその他の行を分けてソートし、さらにクリックするたびに昇順降順を切り替えたり、ページングや編集操作を行ってもソーティング結果に破綻が無いようにするにはかなり手を加える必要があります。

そのあたりを考えてサンプルコードを書いてみました。そのコードを下にアップしておきます。ポイントは、コード内のコメントにも書きましたのでそれを見てください。(手抜きでスミマセン)

.aspx.cs

using System;
using System.Web.UI.WebControls;

namespace WebApplication1
{
    public partial class GridViewSorting : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            // ポストバック前の SELECT クエリを ViewState に保持しておき、
            // Load イベントで SqlDataSource.SelectCommand に設定する。
            // これをしないとページングなどでポストバックしたときソート
            // されなくなってしまう
            string selectQuery = (string)ViewState["CurrectSelectQuery"];
            if (!string.IsNullOrEmpty(selectQuery))
            {
                SqlDataSource1.SelectCommand = selectQuery;
            }
        }

        // GridView で AllowPaging="True" とし、CommandName="Sort" と設定
        // されているヘッダの LinkButton をクリックすると Sorting イベント
        // が発生する。そのハンドラで SqlDataSource.SelectCommand の書き換
        // えを行う。        
        protected void GridView1_Sorting(object sender, GridViewSortEventArgs e)
        {
            GridView gv = (GridView)sender;
            string exp = e.SortExpression;
            string dir = "";

            // ISNUMERIC(exp) は exp が数字の場合 1 に、それ以外は 0 になる。
            // 昇順で数字の行が先に来るようにするには ORDER BY ISNUMERIC(exp)
            // に DESC を、降順の場合は ASC を付与するために使う
            string dirRev = "";

            // GridView に独自属性 CurrentSortField, CurrentSortDir が
            // 追加してある。それにポストバック前のソート対象フィールドと昇順
            // 降順の情報を保持しておく。それと、e.SortExpression の情報を元
            // に SELECT クエリの ORDER BY 句を組み立てる
            if (gv.Attributes["CurrentSortField"] != null &&
                gv.Attributes["CurrentSortDir"] != null)
            {
                // ユーザーが同じヘッダの LinkButton を繰り返しクリックした
                // 場合は昇順降順を切り替える
                if (exp == gv.Attributes["CurrentSortField"])
                {
                    if (gv.Attributes["CurrentSortDir"] == "ASC")
                    {
                        dir = "DESC";
                        dirRev = "ASC"; 
                        gv.Attributes["CurrentSortDir"] = "DESC";
                    }
                    else
                    {
                        dir = "ASC";
                        dirRev = "DESC";
                        gv.Attributes["CurrentSortDir"] = "ASC";
                    }
                }
                // 初期画面から LinkButton クリック、または前と違う LinkButton
                // をクリックした場合
                else
                {
                    gv.Attributes["CurrentSortField"] = exp;
                    dir = "ASC";
                    dirRev = "DESC";
                    gv.Attributes["CurrentSortDir"] = "ASC";
                }
            }

            // SELECT クエリの ORDER BY 句の組み立て、
            // SqlDataSource.SelectCommandプロパティ への設定
            SqlDataSource1.SelectCommand = "SELECT [ID], [Name], [Note] FROM [TestTable] " +
                $"ORDER BY ISNUMERIC([{exp}]) {dirRev}, " +
                $"CASE WHEN ISNUMERIC([{exp}]) = 1 THEN CAST([{exp}] AS FLOAT) ELSE 0 END {dir}, " +
                $"[{exp}] {dir}";

            // SELECT クエリを ViewState に保持
            ViewState["CurrectSelectQuery"] = SqlDataSource1.SelectCommand;

            // 組み込みのソーティングをキャンセルする
            e.Cancel = true;

            // 編集モードに入ったままページングすると編集する行がズレてしまうので
            // ここで編集モードを解除
            gv.EditIndex = -1;
        }

        // 上の Sorting イベントのハンドラでソーティングをキャンセルすると
        // SortedAscendingHeaderStyle, SortedDescendingHeaderStyle
        // プロパティを使ってヘッダに ↑ とか ↓ の画像などの CSS を設定し
        // ても適用されない。なので、以下のようなコードを書いてソート対象
        // にしたヘッダに動的に css を適用する
        protected void GridView1_RowCreated(object sender, GridViewRowEventArgs e)
        {
            string field = GridView1.Attributes["CurrentSortField"];

            if (e.Row.RowType == DataControlRowType.Header &&
                !string.IsNullOrEmpty(field))
            {
                LinkButton lb = e.Row.FindControl(field) as LinkButton;

                if (lb != null)
                {
                    if (GridView1.Attributes["CurrentSortDir"] == "ASC")
                    {
                        lb.CssClass = "sortasc-header";
                    }
                    else if (GridView1.Attributes["CurrentSortDir"] == "DESC")
                    {
                        lb.CssClass = "sortdesc-header";
                    }
                }
            }
        }
    }
}

.aspx

<%@ Page Language="C#" AutoEventWireup="true" 
    CodeBehind="GridViewSorting.aspx.cs" 
    Inherits="WebApplication1.GridViewSorting" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>GridView Sorting</title>
    <style type="text/css">
        .sortasc-header {
            background: url(img/sort-asc.png) right center no-repeat;
        }

        .sortdesc-header {
            background: url(img/sort-desc.png) right center no-repeat;
        }

        th a
        {
            padding-right: 20px;
        } 
    </style>
</head>
<body>
    <form id="form1" runat="server">
        <asp:SqlDataSource ID="SqlDataSource1" runat="server" 
            ConnectionString="<%$ ConnectionStrings:TestDatabaseConnectionString %>" 
            DeleteCommand="DELETE FROM [TestTable] WHERE [ID] = @ID" 
            InsertCommand="INSERT INTO [TestTable] ([Name], [Note]) VALUES (@Name, @Note)" 
            SelectCommand="SELECT [ID], [Name], [Note] FROM [TestTable]" 
            UpdateCommand="UPDATE [TestTable] SET [Name] = @Name, [Note] = @Note WHERE [ID] = @ID">
            <DeleteParameters>
                <asp:Parameter Name="ID" Type="Int32" />
            </DeleteParameters>
            <InsertParameters>
                <asp:Parameter Name="Name" Type="String" />
                <asp:Parameter Name="Note" Type="String" />
            </InsertParameters>
            <UpdateParameters>
                <asp:Parameter Name="Name" Type="String" />
                <asp:Parameter Name="Note" Type="String" />
                <asp:Parameter Name="ID" Type="Int32" />
            </UpdateParameters>
        </asp:SqlDataSource>

        <%--GridView に独自属性 CurrentSortField, CurrentSortDir 
            を追加。それにも ViewState は有効で、ポストバック前のソート
            対象フィールドと昇順降順の情報を保持できる--%>
        <asp:GridView ID="GridView1" runat="server" 
            AllowPaging="True" 
            AllowSorting="True" 
            AutoGenerateColumns="False" 
            DataKeyNames="ID" 
            DataSourceID="SqlDataSource1" 
            CurrentSortField=""
            CurrentSortDir=""
            OnRowCreated="GridView1_RowCreated" 
            OnSorting="GridView1_Sorting">
            <Columns>
                <asp:CommandField ShowDeleteButton="True" 
                    ShowEditButton="True" ShowSelectButton="True" />
                <asp:TemplateField HeaderText="ID" 
                    InsertVisible="False" SortExpression="ID">
                    <EditItemTemplate>
                        <asp:Label ID="Label1" runat="server" 
                            Text='<%# Eval("ID") %>'></asp:Label>
                    </EditItemTemplate>
                    <HeaderTemplate>
                        <asp:LinkButton ID="ID" runat="server" 
                            CommandName="Sort" CommandArgument="ID">
                            ID
                        </asp:LinkButton>
                    </HeaderTemplate>
                    <ItemTemplate>
                        <asp:Label ID="Label1" runat="server" 
                            Text='<%# Bind("ID") %>'></asp:Label>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Name" SortExpression="Name">
                    <EditItemTemplate>
                        <asp:TextBox ID="TextBox1" runat="server" 
                            Text='<%# Bind("Name") %>'></asp:TextBox>
                    </EditItemTemplate>
                    <HeaderTemplate>
                        <asp:LinkButton ID="Name" runat="server" 
                            CommandName="Sort" CommandArgument="Name">
                            Name
                        </asp:LinkButton>
                    </HeaderTemplate>
                    <ItemTemplate>
                        <asp:Label ID="Label2" runat="server" 
                            Text='<%# Bind("Name") %>'></asp:Label>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Note" SortExpression="Note">
                    <EditItemTemplate>
                        <asp:TextBox ID="TextBox2" runat="server" 
                            Text='<%# Bind("Note") %>'></asp:TextBox>
                    </EditItemTemplate>
                    <HeaderTemplate>
                        <asp:LinkButton ID="Note" runat="server" 
                            CommandName="Sort" CommandArgument="Note">
                            Note
                        </asp:LinkButton>
                    </HeaderTemplate>
                    <ItemTemplate>
                        <asp:Label ID="Label3" runat="server" 
                            Text='<%# Bind("Note") %>'></asp:Label>
                    </ItemTemplate>
                </asp:TemplateField>
            </Columns>
        </asp:GridView>
    </form>
</body>
</html>

上のコードを実行し、ヘッダの Name をクリックすると以下のようになります。

ソート結果

Tags: , , , ,

ASP.NET

SqlDataSource を使わず GridView をソート

by WebSurfer 2018年10月22日 13:15

SqlDataSource などのデータソースコントロールを使わないで GridView の各列にソート機能を実装するにはどうすればいいかということを書きます。

GridView の Sorting

元は MSDN Forum のスレッド「SqlDataSourceを使わずに、GridViewの並べ替えができますでしょうか?」の話です。

MSDN ライブラリ GridView Class の「データへのバインド」のセクションに書いてありますが、GridView はデータソースコントロール(SqlDataSource, ObjectDataSource など)と連携して並べ替え、更新、削除、およびページング機能を提供しています。

逆に言えば、データソースコントロールを使わないと、ソート、更新、削除、およびページング機能が必要な場合、全て自力でコードを書いて実装することになります。

以下に、例としてソート機能を自力で GridView に実装する方法を書きます。

ソートを行うために GridView と SqlDataSource の中でどのような操作が行われているかは不明ですが、おそらく、取得したデータから DataView を作って、その Sort プロパティ に SortExpression を設定し、ソートした結果を GirdView に表示していると思われます。

そのあたりの処理を自力でコードを書いて実装してみます。

昇順に並べ替えるだけなら、GridView.Sorting イベントのハンドラで、DataView の Sort プロパティを引数の GridViewSortEventArgs オブジェクトから取得できる SortExpression に設定するだけで可能です。

SqlDataSource + GridView を使った場合、同じ LinkButton のクリックを繰り返すと ASC / DESC が切り替わりますが、そこまで同じにしようとするとちょっと面倒です。

SqlDataSource + GridView でそれをどのように実現しているか分かりませんが、GridView の属性に CurrentSortField, CurrentSortDir というのを追加し、それに前回クリックされた LinkButton の SortExpression およびその時 ASC or DESC どちらだったかの情報を保持することを考えてみました。

そのソースコードを以下にアップしておきます。このコードの実行結果が上の画像の GridView です。ヘッダの Name を 2 回クリックして降順に並べ替えています。

.aspx.cs ファイル

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;

public partial class _0055_GridViewSorting : System.Web.UI.Page
{
    // データソース用の DataView を作成
    protected DataView CreateDataSource()
    {
        DataTable dt = new DataTable();
        DataRow dr;

        dt.Columns.Add(new DataColumn("ID", typeof(Int32)));
        dt.Columns.Add(new DataColumn("Name", typeof(string)));
        dt.Columns.Add(new DataColumn("Type", typeof(string)));
        dt.Columns.Add(new DataColumn("Price", typeof(Int32)));
        dt.Columns.Add(new DataColumn("Qty", typeof(Int32)));
        dt.Columns.Add(new DataColumn("Amount", typeof(Int32)));
        dt.Columns.Add(new DataColumn("CatID", typeof(Int32)));
        dt.Columns.Add(new DataColumn("Note", typeof(string)));
        dt.Columns.Add(new DataColumn("Disc", typeof(bool)));
        dt.Columns.Add(new DataColumn("Date", typeof(DateTime)));

        for (int i = 0; i < 15; i++)
        {
            dr = dt.NewRow();
            dr["ID"] = i;
            dr["Name"] = "Product Name_" + i.ToString();
            dr["Type"] = "Product Type " + (100 - i).ToString();
            dr["Price"] = 123000 * (i + 1);
            dr["Qty"] = (i + 1) * 20;
            dr["Amount"] = 123000 * (i + 1) * (i + 1);
            dr["CatID"] = 100 - i;
            dr["Note"] = "Note_" + i.ToString();
            dr["Disc"] = (i % 2 == 0) ? true : false;
            dr["Date"] = DateTime.Now.AddDays(i);
            dt.Rows.Add(dr);
        }
        return new DataView(dt);
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
            GridView1.DataSource = CreateDataSource();
            GridView1.DataBind();
        }
    }

    protected void GridView1_Sorting(object sender, 
                                      GridViewSortEventArgs e)
    {
        GridView gv = (GridView)sender;
        DataView view = CreateDataSource();
        string exp = e.SortExpression;

        // 同じ LinkButton をクリックした場合 ASC / DESC を切り
        // 替えるための処理。
        // GridView の属性に CurrentSortField, CurrentSortDir 
        // を追加し、それに前回クリックされた LinkButton の 
        // SortExpression およびその時 ASC or DESC どちらだった
        // かの情報を保持。
        if (gv.Attributes["CurrentSortField"] != null &&
            gv.Attributes["CurrentSortDir"] != null)
        {
            if (exp == gv.Attributes["CurrentSortField"])
            {
                if (gv.Attributes["CurrentSortDir"] == "ASC")
                {
                    exp = exp + " DESC";
                    gv.Attributes["CurrentSortDir"] = "DESC";
                }
                else
                {
                    exp = exp + " ASC";
                    gv.Attributes["CurrentSortDir"] = "ASC";
                }
            }
            else
            {
                gv.Attributes["CurrentSortField"] = exp;
                exp = exp + " ASC";
                gv.Attributes["CurrentSortDir"] = "ASC";
            }
        }

        view.Sort = exp;
        gv.DataSource = view;
        gv.DataBind();
    }
}

.aspx ファイル

<%@ Page Language="C#" AutoEventWireup="true" 
    CodeFile="0055-GridViewSorting.aspx.cs" 
    Inherits="_0055_GridViewSorting" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:GridView ID="GridView1" runat="server" 
            AllowSorting="True"
            CurrentSortField=""
            CurrentSortDir=""
            onsorting="GridView1_Sorting">
        </asp:GridView>
    </form>
</body>
</html>

上のコードを見ると、自力で一行もコードを書く必要のない SqlDataSource を使う方が正解と思えます。何らかの理由で SqlDataSource を使えない場合でも、上に紹介した MSDN Forum の記事に書いてあるように ObjectDataSource を使うという手段もあります。

Tags: ,

ASP.NET

About this blog

2010年5月にこのブログを立ち上げました。主に ASP.NET Web アプリ関係の記事です。

Calendar

<<  2024年3月  >>
252627282912
3456789
10111213141516
17181920212223
24252627282930
31123456

View posts in large calendar