2011-01-15 5 views
7

Câu hỏi tương đối đơn giản. Tôi có một datagridview, mà tất cả nó làm là hiển thị số liệu thống kê. Không có chỉnh sửa/thêm/xóa các hàng. Datagridview bị ràng buộc vào một List. Tất cả những gì tôi muốn đạt được là để người dùng có thể sắp xếp các cột.Sắp xếp nguồn dữ liệu Datagridview trên Danh sách <T> trong đó T là vô danh

class Market 
{ 
    public int Location {get;set;} 
    public float Value {get;set;} 
    //... 
} 
class City 
{ 
    public String Name {get;set;} 
    //... 
} 

List<Market> _markets; 
List<City> _cities; 
//Lists are populated. 

dataGridView1.DataSource = _markets.Select(market => 
    new { _cities[market.Location].Name, market.Value}).ToList(); 

Như dự kiến, các cột không thể sắp xếp, nhưng thông tin được hiển thị là những gì bạn muốn. Câu hỏi của tôi là làm thế nào để làm cho các loại DataGridView dựa trên loại cột với số tiền ít nhất phức tạp và ít nhất, như mã sẽ được sử dụng nhiều lần trong suốt.

Ứng dụng này được sử dụng để sử dụng DataBase có lượt xem. Các khung nhìn này sau đó đã điền DataGridViews. Các chế độ xem vẫn còn xung quanh, do đó, một giải pháp có thể có thể là:

DataBase.ViewMarketValue temp = new DataBase.ViewMarketValue() 

_markets.ForEach(market => temp.AddViewMarketValueRow(_cities[market.Location].Name, market.Value); 
dataGridView1.DataSource = temp; 

Kết quả này theo mong muốn: một dữ liệu thống kê có tất cả thông tin và có thể sắp xếp. Vấn đề duy nhất là nó có vẻ sai khi sử dụng quan điểm trong khía cạnh này. Vậy tôi nên làm gì đây?

Trả lời

10

Để có thể sắp xếp dữ liệu tự động trong DataGridView, bạn cần một bộ sưu tập triển khai IBindingListView. Trong BCL, các lớp duy nhất triển khai thực hiện giao diện này là DataViewBindingSource (nhưng sau này chỉ hỗ trợ sắp xếp nếu nguồn dữ liệu bên dưới hỗ trợ nó).

Vì vậy, bạn có một vài lựa chọn:

  • tạo DataTable để giữ dữ liệu, và ràng buộc nó vào DataGridView (nó sẽ thực sự liên kết với DefaultView của DataTable)
  • tạo bộ sưu tập của riêng bạn lớp triển khai IBindingListView
  • sử dụng triển khai hiện tại, như lớp AdvancedList<T> do Marc Gravell đăng trong this post. Bạn cũng sẽ cần phải thêm một constructor để xây dựng danh sách từ kết quả của truy vấn của bạn:

    public AdvancedList(IEnumerable<T> collection) 
    { 
        foreach (var item in collection) 
        { 
         Add(item); 
        } 
    } 
    

Kể từ khi kết quả của truy vấn của bạn là một loại vô danh, bạn sẽ không thể gọi các nhà xây dựng trực tiếp. Cách dễ nhất để giải quyết vấn đề này là tận dụng suy luận kiểu, bằng cách tạo một phương thức chung để tạo danh sách. Để thuận tiện, bạn có thể tạo nó như một phương pháp khuyến nông:

public static AdvancedList<T> ToAdvancedList<T>(this IEnumerable<T> source) 
{ 
    return new AdvancedList<T>(source); 
} 

Sau đó, bạn có thể sử dụng nó như thế:

dataGridView1.DataSource = _markets.Select(market => 
    new { _cities[market.Location].Name, market.Value}).ToAdvancedList(); 
+0

giải pháp rất tốt! Khiếu nại duy nhất của tôi (và nó là một khiếu nại nhỏ) là việc phân loại không nhanh như lý tưởng, nhưng nó có thể chấp nhận được và điều tốt nhất cho đến nay. –

+1

Nó chậm vì nó sử dụng sự phản chiếu để có được giá trị tài sản. Bạn có thể dễ dàng sửa đổi lớp PropertyComparer để nó tạo ra một đại biểu khi nó được tạo ra, và sử dụng ủy nhiệm này thay vì property.GetValue –

+0

@ThomasLevesque nó sẽ là tuyệt vời nếu bạn có thể đăng một số đoạn mã để thực hiện đề xuất của bạn. Cảm ơn – Esen