2016-01-22 2 views
10

私はdatagridviewのWindowsフォームを持っています。すべてのdatagridviewカラムをソート可能にする

理想的な状況:クリックされた列に数字が含まれている場合は、私が上に最低数をしたいと思い、

ユーザーは、9列のいずれかをクリックすると、プログラムは、すべてのデータをソートします。クリックされた列に文字列が含まれている場合は、アルファベット順(A〜Z)にソートされたいと思います。

私が今持っている何

私は「」ヘッダをクリックしたときにOPがDataGridViewのをソートする方法をスタックオーバーフロー上の古い質問を見ました。私の違いは、DataGridViewを9つの列のいずれかでソート可能にしたいということです。

私は私が見つけた質問から盗まれた、このコードを持っている:

dataGridView2.DataSource = listPlayers.Select(s => new { voornaam = s.Voornaam, 
                 Achternaam = s.Achternaam, 
                 positie = s.Positie, 
                 Nationaltieit = s.Nationaliteit, 
                 Leeftijd = s.Age, 
                 Aanval = s.Aanval, 
                 Verdediging = s.Verdediging, 
                 Gemiddeld = s.Gemiddeld, 
                 waarde = s.TransferWaarde }) 
            .OrderBy(s => s.Achternaam) 
            .ToList(); 

foreach(DataGridViewColumn column in dataGridView2.Columns) 
    { 
     dataGridView2.Columns[column.Name].SortMode = 
            DataGridViewColumnSortMode.Automatic; 
    } 

彼は9列のいずれかをクリックしたときにのみ、「Achternaam」によってユーザ注文をすることができます。私が望むのは、ユーザーがNationaliteit列をクリックすると、データがAnの上にソートされます。ようにすべての列

のためにこれはlistplayersリストです:

namespace SimulatorSimulator 
{ 
    class SpelerData 
    { 
     public string Voornaam { get; set; } 
     public string Achternaam { get; set; } 
     public string Positie { get; set; } 
     public string Nationaliteit { get; set; } 
     public int Age { get; set; } 
     public int Aanval { get; set; } 
     public int Verdediging { get; set; } 
     public int Gemiddeld { get; set; } 
     public string TransferWaarde { get; set; } 
    } 
} 

とメインクラスで:

List<SpelerData> listPlayers = new List<SpelerData>(); 

いくつかのダミーデータ:あなたが使用することができ

Romelu;Lukaku;Aanvaller;Belgie;22;87;12;50;41.000.000,00  
Raheem ;Sterling;Aanvaller;Engeland;21;84;30;57;35.000.000,00  
Zlatan ;Ibrahimovic;Aanvaller;Zweden;34;87;21;54;34.500.000,00 
+0

@KevinTinnemansイワンの答えに対するイワン・ストーワのコメントをより慎重に考えてください。私は自分の答えを投稿してから間違っているかもしれませんが、受け入れられた答えはあなたがどんなに良い方法でも開発者になるのを助けません。ブルートフォースは飛び降りるポイントであり、あなたがより良い解決策を思い付くことができない時に、この特定の問題のためにいくつかがあります。これは悪い習慣と管理不能なコードにつながります。 –

答えて

5

をクリックしたときに、私はあなたのケースのための最も簡単な方法は、Databaseテーブルにデータを我慢するだろうと思いますソートできるようになります。このように、dataGridView2の場合はdata sourceとするだけで簡単に並べ替えることができ、ヘッダ列をクリックすることで簡単にソートを行うことができます。

他の回答も示唆しているように、代わりの方法はSortableBindingListarticle)を使用することです。

しかし、両方のオプションは、あなたの選択肢の中でないならば、私は考えることができ、次の最も簡単な方法は、ColumnHeaderMouseClickからイベントを作成することで、その後、あなたはあなたのe.ColumnIndexを利用することによって、それに応じて仕分けし、右の「マッピング」(辞書)をリストできごIEnumerable<SpelerData>

だから、フォームのロード中に、あなたはこのような何かを準備:

Dictionary<int, IEnumerable<SpelerData>> queryDict = new Dictionary<int, IEnumerable<SpelerData>>(); //Prepare a dictionary of query 
private void form_load(object sender, EventArgs e) { 
    dataGridView2.DataSource = listPlayers.OrderBy(x => x.Achternaam).ToList(); 
    queryDict.Add(0, listPlayers.OrderBy(x => x.Voornaam)); 
    queryDict.Add(1, listPlayers.OrderBy(x => x.Achternaam)); 
    queryDict.Add(2, listPlayers.OrderBy(x => x.Positie)); 
    queryDict.Add(3, listPlayers.OrderBy(x => x.Nationaliteit)); 
    queryDict.Add(4, listPlayers.OrderBy(x => x.Age)); 
    queryDict.Add(5, listPlayers.OrderBy(x => x.Aanval)); 
    queryDict.Add(6, listPlayers.OrderBy(x => x.Verdediging)); 
    queryDict.Add(7, listPlayers.OrderBy(x => x.Gemiddeld)); 
    queryDict.Add(8, listPlayers.OrderBy(x => x.TransferWaarde)); 
} 

そしてColumnHeaderMouseClickイベントでは、単に実行します。

private void dataGridView2_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) { 
    dataGridView2.DataSource = queryDict[e.ColumnIndex].ToList(); 
} 

あなたが望む動作が得られます。

IEnumerableは実行が遅延しているため、Dictionaryの早期の準備はパフォーマンスにまったく影響しないことに注意してください。追加する必要があるのは、dataGridView2_ColumnHeaderMouseClickイベントで、辞書を準備するform_Loadと9行のコードの9行のコードだけです。これは私が考えることができる前述の2つを除いて、最も簡単な解決策です。

+1

*「これは私が考えることができる前述の2つを除いて最も簡単な解決策です。」*これは特定のケースでは機能しますが、解決策よりも回避策です。別のグリッドで同じコードが必要な場合はどうなりますか? 3番目のグリッドなど?また、データソースの再割り当ては非常に非効率的で、副作用があります。 'IBindingList'と' IBindingListView'インターフェースは、これと同様のシナリオを扱うために特別に作られています。ベースジェネリッククラスを作成すると、より多くのコーディングが可能になりますが、それは一度の作業であり、何千もの場所で再利用できるため、価値があります。 –

4

SortableBindingList

SortableBindingList<T> list = new SortableBindingList<T>(); 

//Add items to list 

dataGridView.DataSource = list ; 

これは、列ヘッダ

public class SortableBindingList<T> : BindingList<T> 
{ 
    private readonly Dictionary<Type, PropertyComparer<T>> comparers; 
    private bool isSorted; 
    private ListSortDirection listSortDirection; 
    private PropertyDescriptor propertyDescriptor; 

    public SortableBindingList() 
     : base(new List<T>()) 
    { 
     this.comparers = new Dictionary<Type, PropertyComparer<T>>(); 
    } 

    public SortableBindingList(IEnumerable<T> enumeration) 
     : base(new List<T>(enumeration)) 
    { 
     this.comparers = new Dictionary<Type, PropertyComparer<T>>(); 
    } 

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

    protected override bool IsSortedCore 
    { 
     get { return this.isSorted; } 
    } 

    protected override PropertyDescriptor SortPropertyCore 
    { 
     get { return this.propertyDescriptor; } 
    } 

    protected override ListSortDirection SortDirectionCore 
    { 
     get { return this.listSortDirection; } 
    } 

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

    protected override void ApplySortCore(PropertyDescriptor property, ListSortDirection direction) 
    { 
     List<T> itemsList = (List<T>)this.Items; 

     Type propertyType = property.PropertyType; 
     PropertyComparer<T> comparer; 
     if (!this.comparers.TryGetValue(propertyType, out comparer)) 
     { 
      comparer = new PropertyComparer<T>(property, direction); 
      this.comparers.Add(propertyType, comparer); 
     } 

     comparer.SetPropertyAndDirection(property, direction); 
     itemsList.Sort(comparer); 

     this.propertyDescriptor = property; 
     this.listSortDirection = direction; 
     this.isSorted = true; 

     this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1)); 
    } 

    protected override void RemoveSortCore() 
    { 
     this.isSorted = false; 
     this.propertyDescriptor = base.SortPropertyCore; 
     this.listSortDirection = base.SortDirectionCore; 

     this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1)); 
    } 

    protected override int FindCore(PropertyDescriptor property, object key) 
    { 
     int count = this.Count; 
     for (int i = 0; i < count; ++i) 
     { 
      T element = this[i]; 
      if (property.GetValue(element).Equals(key)) 
      { 
       return i; 
      } 
     } 

     return -1; 
    } 
} 
1

リフレクションを使用する場合は、次のようなことができます。

注:私はあなたがDataGridView.ColumnHeaderMouseClick Eventを使用していると仮定していますが、この方法の核心は変わりません。要は、OrderByにする列の名前を表す文字列値を動的に識別する必要があります。あなたが本当に必要な/希望している場合は、この関連付けをハードコードすることができます。

private void dataGridView2_ColumnHeaderMouseClick(
    object sender, DataGridViewCellMouseEventArgs e) 
{ 
    ... 
    var sortCol = dataGridView2.Columns[e.ColumnIndex]; 
    var colName = sortCol.Name; 

    dataGridView2.DataSource = listPlayers.Select(s => new { voornaam = s.Voornaam, Achternaam = s.Achternaam, positie = s.Positie, Nationaltieit = s.Nationaliteit, Leeftijd = s.Age, Aanval = s.Aanval, Verdediging = s.Verdediging, Gemiddeld = s.Gemiddeld, waarde = s.TransferWaarde }) 
              .OrderBy(s => typeof(SpelerData).GetProperty(colName)) 
              .ToList(); 
    ... 
} 
関連する問題