2016-01-22 23 views
10

Tôi có biểu mẫu Windows với datagridview.Thực hiện tất cả các cột datagridview có thể sắp xếp

Tình hình lý tưởng:

Người dùng nhấp vào bất kỳ chín cột, và chương trình sắp xếp tất cả các dữ liệu, nếu cột nhấp chứa số, tôi xin số thấp nhất trên đỉnh. Nếu cột được nhấp có chứa một chuỗi, tôi muốn nó được sắp xếp theo thứ tự bảng chữ cái (A-Z).

Những gì tôi có ngay bây giờ:

tôi thấy một câu hỏi cũ trên Stack Overflow nơi OP làm thế nào để sắp xếp các datagridview khi nhấp "a" tiêu đề. Sự khác biệt với tôi là tôi muốn datagridview của tôi có thể được sắp xếp bởi bất kỳ trong số chín cột.

tôi có mã này, bị đánh cắp từ các câu hỏi tôi thấy:

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; 
    } 

này chỉ cho phép trình tự người dùng bằng cách "Achternaam" khi nhấp chuột một trong chín cột. Những gì tôi muốn là khi người dùng nhấp vào cột Nationaliteit, dữ liệu được sắp xếp với An trên đầu trang. Và như vậy cho mỗi cột

Đây là listplayers danh sách:

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; } 
    } 
} 

và trong lớp học chính:

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

Một số dữ liệu giả:

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 Vui lòng xem xét nhận xét của Ivan Stoev về câu trả lời của Ian kỹ lưỡng hơn. Tôi có thể bị quấy rầy vì đã nói như vậy, và điều này có thể được hiểu sai kể từ khi tôi đăng câu trả lời của riêng tôi, nhưng câu trả lời được chấp nhận sẽ không giúp bạn trở thành một nhà phát triển tốt hơn theo bất kỳ cách nào. Lực lượng vũ phu là một điểm nhảy vọt, và là thứ bạn rơi trở lại khi bạn không thể đưa ra một giải pháp tốt hơn - mà có một số giải pháp cho vấn đề cụ thể này. Điều này sẽ dẫn đến thực tiễn không tốt và mã không thể quản lý được. –

Trả lời

5

Tôi nghĩ rằng cách đơn giản nhất cho trường hợp của bạn sẽ được đưa lên dữ liệu của bạn trong một bảng Database. Bằng cách này, bạn có thể chỉ cần sử dụng điều này làm data source cho số dataGridView2 và bạn sẽ có thể thực hiện việc sắp xếp dễ dàng bằng cách nhấp vào cột tiêu đề.

Một cách khác sẽ là sử dụng SortableBindingList (article) vì câu trả lời khác cũng đã đề xuất. Nhưng nếu cả hai tùy chọn không nằm trong lựa chọn của bạn, cách đơn giản nhất tôi có thể nghĩ là tạo sự kiện từ ColumnHeaderMouseClick và sau đó bạn có thể liệt kê sắp xếp của mình theo cách sử dụng e.ColumnIndex và phải "ánh xạ" (Từ điển) để bạn chuẩn bị IEnumerable<SpelerData>

Vì vậy, trong tải biểu mẫu, bạn làm điều gì đó như thế này:

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)); 
} 

Và sau đó trong trường hợp ColumnHeaderMouseClick, chỉ cần làm:

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

Và bạn sẽ nhận được hành vi mà bạn muốn.

Lưu ý rằng kể từ khi IEnumerable bị trì hoãn thực hiện, việc chuẩn bị sớm của Dictionary sẽ không có tác động đến hiệu suất cả. Điều duy nhất bạn cần thêm là 9 dòng mã trong form_Load để chuẩn bị từ điển và 1 dòng mã trong sự kiện dataGridView2_ColumnHeaderMouseClick của bạn. Đây là giải pháp đơn giản nhất ngoài hai giải pháp mà tôi đã đề cập trước đó mà tôi có thể nghĩ đến.

+1

* "Đây là giải pháp đơn giản nhất ngoài hai giải pháp mà tôi đã đề cập trước đó mà tôi có thể nghĩ đến." * Trong khi điều này làm việc cho trường hợp cụ thể, nó giải quyết nhiều hơn một giải pháp. Điều gì sẽ xảy ra nếu bạn cần cùng một mạng lưới khác - thêm 10 dòng mã khác? Lưới thứ ba, v.v ...? Cũng chỉ định lại nguồn dữ liệu là không hiệu quả cao và có tác dụng phụ. Các giao diện 'IBindingList' và' IBindingListView' được đặc biệt thực hiện để xử lý trường hợp này và các kịch bản tương tự. Tạo một lớp chung chung cơ bản có thể trông mã hóa nhiều hơn, nhưng nó có giá trị bởi vì nó là một nỗ lực một lần và có thể được tái sử dụng trên hàng ngàn địa điểm. –

4

Bạn có thể sử dụng một SortableBindingList

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

//Add items to list 

dataGridView.DataSource = list ; 

này sẽ cho phép sắp xếp khi nhấp vào tiêu đề cột

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

Nếu bạn sẵn sàng sử dụng sự phản chiếu, bạn có thể làm điều gì đó như sau.

LƯU Ý: Tôi giả sử bạn đang sử dụng DataGridView.ColumnHeaderMouseClick Event, nhưng điều đó không làm thay đổi cốt lõi của phương pháp này. Vấn đề là bạn cần phải tự động xác định giá trị chuỗi đại diện cho tên của cột bạn muốn OrderBy. Bạn có thể hardcode hiệp hội này nếu bạn thực sự cần thiết/muốn.

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(); 
    ... 
} 
Các vấn đề liên quan