こんにちわ。
環境:XP SP2
VB.NET 2005
GridViewでDataBindした際に特定のカラムに対してソートする方法を探しています。
GridViewの記述はこんな感じです
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
<asp:GridView ID=grd_Main runat=server AllowSorting=True
AutoGenerateColumns=False
DataKeyNames=ID style=border:none; AllowPaging=True PageSize=100
SortDirection=Ascending>
<RowStyle CssClass=GridDetail1 HorizontalAlign=Left />
<SelectedRowStyle BackColor=LightSteelBlue />
<PagerStyle CssClass=item />
<HeaderStyle CssClass=GridHeader />
<AlternatingRowStyle CssClass=GridDetail2 HorizontalAlign=Left />
<Columns>
<asp:BoundField DataField=ID HeaderText=ID
SortExpression=ID >
<ItemStyle Width=120px />
</asp:BoundField>
<asp:BoundField DataField=OPERATION HeaderText=処理内容
SortExpression=OPERATION >
<ItemStyle Width=120px />
</asp:BoundField>
<asp:BoundField DataField=RESULT HeaderText=処理結果
SortExpression=RESULT >
<ItemStyle Width=120px />
</asp:BoundField>
<asp:BoundField DataField=INFO HeaderText=インフォメーショ
ン SortExpression=INFO >
<ItemStyle Width=302px />
</asp:BoundField>
</Columns>
<PagerSettings Visible=False />
</asp:GridView>
↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
デフォルトではIDの昇順になっていますが、これを処理結果にによって並び替えたいで
す。
DataKeyNamesをRESULTにしたり、
DataBindingイベントを拾ってSortDirectionプロパティをいじろうとしましたが
(SortDirectionプロパティはReadOnlyだよと怒られた)うまくいきませんでした。
何かよい方法がありましたら教えていただきたいです。
よろしくお願いします。
バインドする前にデータソースの側をソートしておけばいいんじゃないかなぁ。
> シャノンさん
回答ありがとうございます。
バインド→ソート ではなく、
ソート→バインド の順でやったらいいんじゃないの?ってことですよね。
DataBindの箇所をおおざっぱに書くと
Dim GDt As New Data.DataTable
:
:
grd_Main.DataSource = GDt
grd_Main.DataBind()
こうなっていますが、
grd_Main.DataBind()の前にGDtをいじれって感じですかね。
ちょっと調べていじくってみます。
> バインド→ソート ではなく、
> ソート→バインド の順でやったらいいんじゃないの?ってことですよね。
そうです。
GridView のデータソースとしては、IEnumerable を実装するクラスが使えるらしいで
す。
で、IEnumerable にはソート機能がありません。
つまり、GridView には、ソートできるデータソースも、ソートできないデータソースも
バインドできるということです。
ですから、GridView の側から、どんなデータソースであってもソートする汎用的な方法
は無いのではないか? と思います。
> Dim GDt As New Data.DataTable
DataTable にもソート機能はありませんが、DataView を使えばソートすることが可能で
す。
> つまり、GridView には、ソートできるデータソースも、
> ソートできないデータソースもバインドできるということです。
> ですから、GridView の側から、どんなデータソースであってもソートする
> 汎用的な方法は無いのではないか? と思います。
なるほどです。
GridViewはそれだけ柔軟性のあるコントロールということですね。
> DataTable にもソート機能はありませんが、
> DataView を使えばソートすることが可能です。
これについては、
http://www.atmarkit.co.jp/fdotnet/dotnettips/363dtsort/dtsort.html
を参考に実装してみました。
'データテーブルのコピーを作成
Dim GDt2 As Data.DataTable = GDt.Clone
'ソートされたデータビューの作成
Dim DataView As New Data.DataView(GDt)
DataView.Sort = RESULT
'ソートされたレコードのコピー
For Each dvr As Data.DataRowView in DataView
GDt2.ImportRow(dvr.Row)
Next
これでソートはできるようになりました。
ありがとうございました。
もうひとつ疑問なんですが、ソート対象のカラムの値は現在アルファベットの文字列にな
っていて(OK,NG,WARNINGなど)、ソートするとアルファベット順にソートされます。
これをアルファベット順ではなくN-W-Oのように希望の順番で並べることは可能でしょう
か?
やれるとしたら…それぞれの文字列に数値を割り当てておいて、その数値を対象にソート
する…とかになるでしょうか?
試行錯誤してみますが、もっといい方法あるよ!というのがあれば教えてくださると助か
ります。
ソートの順番に関してですが、「文字列のソートは文字コードの数値順になっているハズ
だ」ということで、各文字列を定義するヘッダファイル内で
OKの場合 OK(そのまま)
WARNINGの場合 WARNING(スペースをひとつ空ける)
NGの場合 NG(スペースをふたつ空ける)
このように定義し直してやりました。
これで昇順にソートしたとき、NG-WAR-OKの順になります(GridView表示時はスペースは無
視されるので問題なし)。
あまり汎用的なやり方とは言えませんが、暫定的にこれで解決とします。
もっとスマートなやり方については随時募集中です。
ありがとうございました。
DataView を使うなら、
Dim dataView As New Data.DataView(GDt)
dataView.Sort = RESULT
grd_Main.DataSource = dataView
grd_Main.DataBind()
でいいんじゃないかなーと思いますが、どうでしょう?
ただ、これだと、
> これをアルファベット順ではなくN-W-Oのように希望の順番で並べること
はできません。
で、
http://msdn.microsoft.com/ja-jp/library/system.web.ui.webcontrols.gridview.aspx
を読んでみたのですが、
> System.Collections.IEnumerable インターフェイスを実装するデータ ソースに
> バインドするには、プログラムによって GridView コントロールの DataSource
> プロパティをデータ ソースに設定してから、DataBind メソッドを呼び出します。
> このメソッドを使用すると、GridView コントロールは、組み込みの並べ替え、更新、
> 削除、およびページングの各機能を提供しません。適切なイベントを使用して、
> この機能を提供する必要があります。
とありますね。
「適切なイベントを使用して云々」ということは、こういった、それ自体ではソートをサ
ポートしないデータソースであっても、Sorting イベントを捕まえて自分でソートしてや
ればいいのかな? と思います。
もちろん、それは DataTable を使った場合でも可能だと思います。
> もっとスマートなやり方については随時募集中です。
俺は ASP.NET をやったことが無いので的外れなことを言うかもしれません。ここから先
はあまり信じない方がいいかもしれません。
ソートというのは極論すれば、2つの要素を比較し、どっちが前かを判定して、場所を入
れ替えるという作業です。
.NET Framework において、一般的に、比較できるオブジェクトは IComparable(Of T) イ
ンターフェイスを実装します。
OK、NG、WARNING という文字列をメンバに持つクラスを作り、そのクラスで、NG
< WARNING < OK という大小関係になるように IComparable(Of T) を実装して、その配列
をデータソースにすれば、任意の並べ替えが可能かも?
> Dim dataView As New Data.DataView(GDt)
> dataView.Sort = RESULT
> grd_Main.DataSource = dataView
> grd_Main.DataBind()
確かにこれでも大丈夫でした。。。
>「適切なイベントを使用して云々」ということは、こういった、
> それ自体ではソートをサポートしないデータソースであっても、
> Sorting イベントを捕まえて自分でソートしてやればいいのかな?と思います。
実はSortingイベントを捕まえた関数はすでに実装されていて、
各カラムでソートできるようにはなっているのですが、
それとは別に、初回バインド時にソートして出てこないかな~と考えたのです。
> OK、NG、WARNING という文字列をメンバに持つクラスを作り、そのクラスで、
> NG < WARNING < OK という大小関係になるように IComparable(Of T) を実装して、
> その配列をデータソースにすれば、任意の並べ替えが可能かも?
なんとなくですが、そんな感じのイメージを持っていました。
が、実際そうするかどうかは工数と相談することになると思うので、
イザ実装しようとする時にはありがたく参考にさせていただきます。