Binding List <T> กับ DataGridView ใน WinForm


91

ฉันมีชั้นเรียน

class Person{
      public string Name {get; set;}
      public string Surname {get; set;}
}

และสิ่งList<Person>ที่ฉันเพิ่มบางรายการ รายการนี้ผูกไว้กับDataGridViewไฟล์.

List<Person> persons = new List<Person>();
persons.Add(new Person(){Name="Joe", Surname="Black"});
persons.Add(new Person(){Name="Misha", Surname="Kozlov"});
myGrid.DataSource = persons;

ไม่มีปัญหา. myGridแสดงสองแถว แต่เมื่อฉันเพิ่มรายการใหม่ของฉันpersonsรายการmyGridไม่แสดงรายการปรับปรุงใหม่ แสดงเฉพาะสองแถวที่ฉันเพิ่มไว้ก่อนหน้านี้

แล้วปัญหาคืออะไร?

การตอบกลับทุกครั้งใช้งานได้ดี แต่เมื่อผมผูกDataTableตารางเมื่อทุกครั้งที่ฉันจะทำให้การเปลี่ยนแปลงบางอย่างDataTableที่มีอยู่ไม่จำเป็นต้อง myGridrebind

จะแก้ยังไงโดยไม่ตอกกลับทุกครั้ง?

คำตอบ:


188

รายการไม่ได้ใช้งานIBindingListดังนั้นกริดจึงไม่ทราบเกี่ยวกับรายการใหม่ของคุณ

ผูก DataGridView ของคุณกับ a BindingList<T>แทน

var list = new BindingList<Person>(persons);
myGrid.DataSource = list;

แต่ฉันจะไปไกลกว่านั้นและผูกกริดของคุณกับไฟล์ BindingSource

var list = new List<Person>()
{
    new Person { Name = "Joe", },
    new Person { Name = "Misha", },
};
var bindingList = new BindingList<Person>(list);
var source = new BindingSource(bindingList, null);
grid.DataSource = source;

มันบอกว่าคุณสามารถใช้ IList และอินเทอร์เฟซอื่น ๆ ได้เช่นกัน: msdn.microsoft.com/en-us/library/…
Pacane

4
@Pacane: แน่นอนว่าคุณทำได้ แต่ DataGridView จำเป็นต้องรู้ว่าแหล่งข้อมูลของคุณมีการเปลี่ยนแปลงหรือไม่ Oneวิธีคือการใช้ BindingList ซึ่งจะเพิ่มเหตุการณ์หากรายการพื้นฐานมีการเปลี่ยนแปลง อีกวิธีหนึ่งคือการใช้BindingSourceและเรียก ResetBinding () ทุกครั้งที่คุณเพิ่ม / ลบแถว แต่วิธีนั้นจะได้ผลมากกว่า หากคุณต้องการแจ้งให้กริดทราบเกี่ยวกับการเปลี่ยนแปลงคุณสมบัติวิธีที่ง่ายที่สุดคือการนำไปใช้INotifyPropertyChanged
เจอร์เก้นสไตน์บล็อค

5
ทำไมคุณถึงใช้ BindingList และ BindingSource เพราะเราสามารถผูกรายการเข้ากับคุณสมบัติแหล่งข้อมูล datagridview ได้โดยตรง พูดคุยถึงความสำคัญของ BindingList และ BindingSource ที่คุณใช้ที่นี่ ขอบคุณ
Mou

5
@ คุณคุณสามารถผูก DataGrid กับList<T>ถ้าคุณต้องการ แต่ถ้าคุณ programatically เพิ่มรายการในรายการ DataGridView จะไม่ทราบเกี่ยวกับเรื่องนี้เพราะคุณรายการไม่ IBindingListimplent เกี่ยวกับ BindingSource: ฉันใช้ winforms เป็นจำนวนมากและฉันไม่ผูกมัดกับสิ่งอื่นใดนอกจาก BindingSource - FULLSTOP หากต้องการเพิ่มรายละเอียดมากเกินไปสำหรับความคิดเห็น แต่BindingSourceมีข้อเสนอมากมายโดยไม่มีข้อเสีย ฉันจะไปให้ไกลและพูดว่าAnyone who does not use a BindingSource for binding has not fully understood windows forms databindings
Jürgen Steinblock

4
@CraigBrett พิจารณาBindingSourceเป็นสะพานเชื่อมระหว่างแหล่งข้อมูลและ GUI ของคุณ ช่วยแก้ปัญหาที่เกี่ยวข้องกับการเชื่อมโยงฐานข้อมูลมากมาย คุณต้องการโหลดข้อมูลของคุณใหม่หรือไม่? เพียงตั้งค่าbindingSource.DataSourceเป็นคอลเลกชั่นใหม่ของคุณแทนที่จะเชื่อมโยงทุกการควบคุม แหล่งข้อมูลของคุณสามารถเป็นโมฆะ? ตั้งค่าbindingSource.DataSource = typeof(YourClass)คุณต้องการมีกริดที่แก้ไขได้ แต่แหล่งข้อมูลของคุณไม่มีตัวสร้างแบบไม่มีพารามิเตอร์? เพียงใช้bindingSource.AddingNewเหตุการณ์และสร้างวัตถุด้วยตัวคุณเอง ฉันไม่เคยพบข้อเสียในขณะที่ใช้BindingSourceแต่มีประโยชน์มากมาย
Jürgen Steinblock

4

ทุกครั้งที่คุณเพิ่มองค์ประกอบใหม่ในรายการคุณจะต้องผูก Grid ของคุณใหม่ สิ่งที่ต้องการ:

List<Person> persons = new List<Person>();
persons.Add(new Person() { Name = "Joe", Surname = "Black" });
persons.Add(new Person() { Name = "Misha", Surname = "Kozlov" });
dataGridView1.DataSource = persons;

// added a new item
persons.Add(new Person() { Name = "John", Surname = "Doe" });
// bind to the updated source
dataGridView1.DataSource = persons;

ฉันไม่เห็นคุณสมบัติ dataSource ภายใต้ datagrid คุณบอกฉันได้ไหมว่าฉันจะใช้มันได้อย่างไร
RSB

2

ใช่มันเป็นไปได้ที่จะดำเนินการโดยไม่ต้อง rebinding โดยใช้ INotifyPropertyChanged Interface

ตัวอย่างสวย ๆ ง่ายๆมีอยู่ที่นี่

http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx


1
นั่นยังไม่เพียงพอหากคุณใช้INotifyPropertyChangedDataGridView จะแสดงการเปลี่ยนแปลงคุณสมบัติทั้งหมดที่เกิดขึ้นในเบื้องหลัง แต่จะไม่ทราบว่าคุณเพิ่ม / ลบแถวจากแหล่งที่มาของคุณหรือไม่ เพื่อจุดประสงค์นี้มีIBindingListอินเทอร์เฟซและเพื่อความมั่นใจของคุณการปลูกถ่ายBindingList<T>ที่ดำเนินการไปแล้ว แต่ไม่สนับสนุนการเรียงลำดับ / การกรอง
Jürgen Steinblock

1
ใช่ฉันเห็นด้วยกับคุณ ดังนั้นฉันคิดว่า ObservableCollection <T> สามารถใช้กับสิ่งนี้ได้ คุณคิดอย่างไร?
Dev

0

หลังจากเพิ่มรายการใหม่ที่จะpersonsเพิ่ม:

myGrid.DataSource = null;
myGrid.DataSource = persons;

ฉันไม่เห็นคุณสมบัติ dataSource ภายใต้ datagrid คุณบอกฉันได้ไหมว่าฉันจะใช้มันได้อย่างไร
RSB

1
คำแนะนำนี้อาจทำให้เกิดปัญหา ตัวอย่างเช่นคุณจะพบว่าการคลิกบนรายการในตารางอาจทำให้ได้รับIndexOutOfRangeExceptionเนื่องจากแหล่งข้อมูลเป็นค่าว่าง ณ จุดนั้น จะเป็นการดีกว่าที่จะผูกมัดกับBindingListในตอนแรกและใช้INotifyPropertyChangedบนวัตถุของคุณเนื่องจากคำตอบอื่น ๆ ระบุไว้
สตีฟ

อะไรคือจุดที่กำหนดให้nullหากคุณกำหนดให้personsในบรรทัดถัดไปทันที
Rufus L

0

นี่ไม่ใช่ปัญหาที่ฉันมี แต่ถ้าใครก็ตามที่ต้องการแปลง BindingList ประเภทใดก็ได้เป็น List ประเภทเดียวกันนี่คือวิธีการ:

var list = bindingList.ToDynamicList();

นอกจากนี้หากคุณกำหนด BindingLists ประเภทไดนามิกให้กับ DataGridView.DataSource ให้ตรวจสอบให้แน่ใจว่าคุณประกาศเป็น IBindingList ก่อนเพื่อให้ข้างต้นทำงานได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.