Làm cách nào để liên kết một Danh sách <string> với một điều khiển DataGridView?


84

Tôi có một đơn giản List<string>và tôi muốn nó được hiển thị trong một DataGridViewcột.
Nếu danh sách chứa các đối tượng phức tạp hơn, chỉ cần thiết lập danh sách dưới dạng giá trị của thuộc tính của nó DataSource.

Nhưng khi làm điều này:

myDataGridView.DataSource = myStringList;

Tôi nhận được một cột được gọi Lengthvà độ dài của các chuỗi được hiển thị.

Làm thế nào để hiển thị các giá trị chuỗi thực tế từ danh sách trong một cột?

Câu trả lời:


70

Đó là vì DataGridView tìm kiếm các thuộc tính của các đối tượng chứa. Đối với chuỗi chỉ có một thuộc tính - độ dài. Vì vậy, bạn cần một trình bao bọc cho một chuỗi như thế này

public class StringValue
{
    public StringValue(string s)
    {
        _value = s;
    }
    public string Value { get { return _value; } set { _value = value; } }
    string _value;
}

Sau đó, liên kết List<StringValue>đối tượng vào lưới của bạn. Nó hoạt động


3
Cột DataPropertyNamecủa cột phải làValue
Rémi

Còn phân nhóm thì sao? Bây giờ "A" không bằng "A" và tôi có hai nhóm "A".
Rover

97

Thử đi:

IList<String> list_string= new List<String>();
DataGridView.DataSource = list_string.Select(x => new { Value = x }).ToList();
dgvSelectedNode.Show();

Tôi hi vọng cái này giúp được.


13
Nếu bạn đang sử dụng Danh sách thay vì IList, bạn có thể sử dụng List.ConvertAll(x => new { Value = x});.
Scotty.NET

7
Điều này hoạt động nhưng các thay đổi đối với list_string sẽ không cập nhật DataGridView.
Pedro77

Để cập nhật Grid yêu cầu chạy lại câu lệnh linq.
Jeff

1
dgvSelectedNode.Show () là gì?
Duan Walker

18

Phần sau sẽ hoạt động miễn là bạn bị ràng buộc với bất kỳ thứ gì triển khai IEnumerable <string>. Nó sẽ liên kết cột trực tiếp với chính chuỗi, chứ không phải với một Đường dẫn Thuộc tính của đối tượng chuỗi đó.

<sdk:DataGridTextColumn Binding="{Binding}" />

Tôi đã thử nghiệm loại đường này và nó hoạt động đúng. Nó sạch hơn các giải pháp khác.
Gustavo Cardoso

7
Điều này không phải là cụ thể cho ánh sáng bạc?
NoviceProgrammer,

2
điều này cũng hoạt động trong WPF .. tại sao bạn lại ủng hộ một nhận xét không chính xác?
Boppity Bop

4
Phản đối vì câu hỏi ban đầu có thẻ "datagridview", là kiểm soát winforms. Giải pháp này không áp dụng cho winfroms.
VIS

13

bạn cũng có thể sử dụng linq và các loại ẩn danh để đạt được kết quả tương tự với ít mã hơn như được mô tả ở đây .

CẬP NHẬT: blog ngừng hoạt động, đây là nội dung:

(..) Các giá trị hiển thị trong bảng đại diện cho độ dài của chuỗi thay vì giá trị chuỗi (!) Có vẻ lạ, nhưng đó là cách cơ chế ràng buộc hoạt động theo mặc định - với một đối tượng nó sẽ cố gắng liên kết với thuộc tính đầu tiên của nó đối tượng (thuộc tính đầu tiên nó có thể tìm thấy). Khi được truyền vào một cá thể, lớp String, thuộc tính mà nó liên kết với là String.Length vì không có thuộc tính nào khác cung cấp chính chuỗi thực.

Điều đó có nghĩa là để có được quyền ràng buộc của chúng ta, chúng ta cần một đối tượng wrapper sẽ hiển thị giá trị thực của một chuỗi dưới dạng thuộc tính:

public class StringWrapper
    {
     string stringValue;
     public string StringValue { get { return stringValue; } set { stringValue = value; } }

     public StringWrapper(string s)
     {
     StringValue = s;
     }
  }   

   List<StringWrapper> testData = new List<StringWrapper>();

   // add data to the list / convert list of strings to list of string wrappers

  Table1.SetDataBinding(testdata);

Mặc dù giải pháp này hoạt động như mong đợi nhưng nó yêu cầu khá nhiều dòng mã (chủ yếu là để chuyển đổi danh sách chuỗi thành danh sách trình bao bọc chuỗi).

Chúng tôi có thể cải thiện giải pháp này bằng cách sử dụng LINQ và các loại ẩn danh- chúng tôi sẽ sử dụng truy vấn LINQ để tạo danh sách trình bao bọc chuỗi mới (trình bao bọc chuỗi sẽ là một loại ẩn danh trong trường hợp của chúng tôi).

 var values = from data in testData select new { Value = data };

 Table1.SetDataBinding(values.ToList());

Thay đổi cuối cùng mà chúng tôi sẽ thực hiện là chuyển mã LINQ sang một phương thức mở rộng:

public static class StringExtensions
  {
     public static IEnumerable CreateStringWrapperForBinding(this IEnumerable<string> strings)
     {
     var values = from data in strings
     select new { Value = data };

     return values.ToList();
     }

Bằng cách này, chúng ta có thể sử dụng lại mã bằng cách gọi một phương thức trên bất kỳ tập hợp chuỗi nào:

Table1.SetDataBinding(testData.CreateStringWrapperForBinding());

8

Đây là vấn đề phổ biến, một cách khác là sử dụng đối tượng DataTable

DataTable dt = new DataTable();
dt.Columns.Add("column name");

dt.Rows.Add(new object[] { "Item 1" });
dt.Rows.Add(new object[] { "Item 2" });
dt.Rows.Add(new object[] { "Item 3" });

Sự cố này được mô tả chi tiết tại đây: http://www.psworld.pl/Programming/BindingListOfString


2
Tuy nhiên, danh sách <T> có thể lập được dữ liệu nặng hơn, và hầu hết các nhà phát triển sẽ tránh việc sử dụng dữ liệu đó.
Musikero31

2

Bạn có thể gặp phải các vấn đề về hiệu suất khi chỉ định danh sách thực sự lớn thông qua LINQ. Giải pháp sau phù hợp với danh sách lớn và không có chuỗi phân lớp:

Đặt DataGridView (ở đây là "Xem") thành chế độ ảo, tạo cột bạn cần và ghi đè / đăng ký cho sự kiện CellValueNeeded

private void View_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
{
    // Optionally: check for column index if you got more columns
    e.Value = View.Rows[e.RowIndex].DataBoundItem.ToString();
}

thì bạn chỉ cần gán danh sách của mình cho DataGridView:

List<String> MyList = ...
View.DataSource = MyList;

2

Thử đi :

//i have a 
List<string> g_list = new List<string>();

//i put manually the values... (for this example)
g_list.Add("aaa");
g_list.Add("bbb");
g_list.Add("ccc");

//for each string add a row in dataGridView and put the l_str value...
foreach (string l_str in g_list)
{
    dataGridView1.Rows.Add(l_str);
}

1
Bạn nhận ra câu hỏi này giống như 6 tuổi và đã được trả lời đúng không?
Hozikimaru

2
bạn phải thêm cột vào xem DataGrid đầu tiên hoặc này sẽ không hoạt động
deltanine

0

Thay thế là sử dụng một chức năng trợ giúp mới sẽ lấy các giá trị từ Danh sách và cập nhật trong DataGridView như sau:

    private void DisplayStringListInDataGrid(List<string> passedList, ref DataGridView gridToUpdate, string newColumnHeader)
    {
        DataTable gridData = new DataTable();
        gridData.Columns.Add(newColumnHeader);

        foreach (string listItem in passedList)
        {
            gridData.Rows.Add(listItem);
        }

        BindingSource gridDataBinder = new BindingSource();
        gridDataBinder.DataSource = gridData;
        dgDataBeingProcessed.DataSource = gridDataBinder;
    }

Sau đó, chúng ta có thể gọi hàm này theo cách sau:

    DisplayStringListInDataGrid(<nameOfListWithStrings>, ref <nameOfDataGridViewToDisplay>, <nameToBeGivenForTheNewColumn>);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.