ホーム 院内・スタッフ紹介 診療時間・アクセス フォトギャラリー
0574-27-6355

院長のメモ帖

2014年4月30日 水曜日

DataGridViewとBindingList<T>

 .NETでデーターをいじるプログラミングをすると、DataGridViewは非常に便利なコントロールです。SQL ServerにLinqToSQLでクエリした結果をデーターバインドするだけでソート可能な表が作れるので、日常的に多用しています。

 ただ、クエリ結果を演算してローカルのLinqToObjectで匿名型のIEnumerable<T>(具体的にはList<T>)に変換すると、表に表示はできますが、そのままではソートできなくなるのが不便に感じてました。DataSetやらで型情報を作ればいいのですが、せっかく匿名型で簡単にクエリーできるのに、表示のためだけに手間が多すぎて困ってました。

 なんか方法があるはずだと思いながら長年ほかっておきましたが、検索したらカスタムデーターバインド(第2部)にやり方の概論が書いてありました。要するにはIBindingListインターフェースを実装するソート可能なジェネリッククラスを作ればいいということで、具体的にはBindingList<T>を継承した列挙クラスを作り、汎用ソートロジックを組み込んだIComparer<T>を継承したコンペアラークラスを作成し、IBindingListのソートメソッドをオーバーライドすればよいということでした。

 サンプルソースがあったみたいなんですが、ダウンロードできず、HP上のコードは不完全なものだったので参考にしてSortableBindingList<T>を完成させました。コンストラクタでList<T>オブジェクトを受け取りIBindingListに変換し、IComparableな公開プロパティすべてを標準の序列でソートできます。IBindingListにはほかにも機能があるようですが、とりあえずソートできれば用が足りるので他の機能については実装しませんでしたが、とっても便利なクラスを作ることができました。

using System;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel;
using System.Data;

namespace mynamespace
{
   //IBindingListのソート機能を実装したジェネリックリストクラス
    public class SortableBindingList<T> : BindingList<T>
    {
        public static SortableBindingList<T> ToSortableBindingList(List<T> list)
        {
            return new SortableBindingList<T>(list);
        }

        public SortableBindingList(List<T> list) : base(list) { }

        protected override bool SupportsSortingCore
        {
            get
            {
                return true;
            }
        }

        protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
        {
            List<T> items = this.Items as List<T>;
           
            if (items != null)
            {
                PropertyComparer<T> pc = new PropertyComparer<T>(prop, direction);
                items.Sort(pc);
                _isSorted = true;
            }
            else
                _isSorted = false;

            _direction = direction;
            _SortProperty = prop;
            this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
        }

        private bool _isSorted;
        protected override bool IsSortedCore
        {
            get { return _isSorted; }
        }

        private ListSortDirection _direction;
        protected override ListSortDirection SortDirectionCore
        {
            get
            {
                return _direction;
            }
        }

        private PropertyDescriptor _SortProperty;
        protected override PropertyDescriptor SortPropertyCore
        {
            get
            {
                return _SortProperty;
            }
        }
    }

    //汎用コンペアラークラス
    public class PropertyComparer<T> : IComparer<T>
    {
        public PropertyComparer(PropertyDescriptor propertyName, ListSortDirection direction)
        {
            this.name = propertyName;
            sortDirection = (direction == ListSortDirection.Ascending) ? 1 : -1;
        }

        private PropertyDescriptor name;
        private int sortDirection;

        #region IComparer<T> メンバー

        public int Compare(T x, T y)
        {
            IComparable left = name.GetValue(x) as IComparable;
            IComparable right = name.GetValue(y) as IComparable;

            int result;

            if (left != null)
                result =  left.CompareTo(right);
            else if (right == null)
                result = 0;
            else
               result = -1;

            return result * sortDirection;
        }

    //呼び出し用拡張メソッド
    public static class BindingListExtensions
    {
        public static SortableBindingList<T> ToSortableBindingList<T>(this List<T> list)
        {
            return SortableBindingList<T>.ToSortableBindingList(list);
        }
    }

}


投稿者 美濃加茂市のIT獣医師 近藤 博 | コメント(1)

コメントする

名前:

メールアドレス:

コメント:

コメント

初めまして。
そうなんですよね。サンプル「winforms02182005_sample」がないんですよね。
そのサンプル名でググると以下のページが出てきます。
私は、それをもとにVBで仕上げました。


http://www.windows-tech.info/3/faac15e801fb186e.php

こちらに明記されている内容も参照させていただきます。

唐突に連絡を失礼しました。
ありがとうございました。

Posted by Hirai 2016年9月14日 水曜日

カレンダー

2018年11月
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30  

新着情報

一覧を見る

2018/11/09

11/9の午後の診察時間は、
3時から5時までとなります。
ご迷惑をおかけしますが、よろしくお願いします。

2012/03/01

HPを作成しました!
今後とも宜しくお願いします。


大きな地図で見る〒505-0031
岐阜県 美濃加茂市新池町
1-8-28

お問い合わせ 詳しくはこちら
  • RSS配信
  • RSSヘルプ