我們在編程過程中,會涉及到表格數據的顯示,存儲等,就可能涉及到DataGridView,DataSource, DataTable等概念。
下面我就我自己模糊的一些知識點串講以下:
1)首先我要講的是一些控件:
Control: 控件基類,有一個DataBindings對象,它是一個ControlBindingCollection類,這個類繼承與BindingsCollection,里面有一個Binding的列表對象,其中Binding對象時一個記錄了屬性名,數據源,數據成員等的對象。還有個BindingContext的虛屬性對象,這個是記錄了DataSource和DataMember的對象的集合。
DataGridView:繼承與Control,本身還有一個DataSource對象(object),還有一個DataMember(string),他們兩構成了DataGridViewDataConnection對象,這個對象除了這兩個對象引用外,還有DataGridView這個控件,還有一個CurrencyManager,這個CurrencyManager是繼承自BindingManagerBase,根據BindingContext返回指定的CurrencyManager。然后這個BindingMangerBase里面維護了一個IList的列表。可以顯示多列。
ListControl:這控件繼承自Control,本身也有DataSource對象,還有一個DisplayMember和ValueMember屬性,這兩個屬性是BindingMemberInfo對象。只能顯示一列。其繼承類有ListBox,ComboBox.
2)控件大致介紹了下有什么后,接下來就是綁定的源頭了,我們用到了BindingSource類,這個類實現了IBindingList,IBindingList, IList, ICollection接口。BindingSource的成員中有DataSource,這個是個object對象,在賦值后內部構造一個CurrencyManager,這個對象就可以維護資源列表了。
3)那么誰可以賦值給BindingSource呢?一般實現了IList, IListSource(DataTable,DataSet),IBindingList(BindingList<T>),IBindingListView(BindingSource)的對象都可以賦值。
4)也就是說BindingSource是維護數據與控件之間的一個紐帶,它維護一個數據的列表,賦值給控件,控件就可以顯示相應的數據,相當於三者像一根繩上的螞蚱。
5)我們可以看到有兩個屬性:DataBindings, DataSource, 他們都可以跟數據源建立聯系,區別在於:DataBindings一般都是建立控件的屬性與數據源的某個屬性之間的關系,是屬於Control的層次定義的,而DataSource不是屬於Control的,有些控件可能沒有,一般都是給列表控件如ListControl和DataGridView顯示數據用。
6)另外DataGridView和ListControl有幾個屬性有點區別,DataGridView有一個DataMember成員(string),因為我們這個DataGridView有可能綁定到一個DataSet,這個有可能有很多表,或者是一個列表對象,其成員中有子成員也是列表對象,這個時候我們就需要設置DataMember。而ListControl沒有DataMember成員,但是有ValueMember和DisplayMember兩個成員,有什么區別呢?DisplayMember的意思就是指我要顯示哪個成員,當我們綁定一個數據源給這個控件的DataSource后,這個一般都是指一個表類型的數據,然后DisplayMember指定我們要顯示的列名(因為只能顯示一列),然后就塞選出這一列值給顯示出來,然后如果程序要獲得值,那么就要設置ValueMember成員,也就是說我顯示和獲取的值可以是不同的,比如我顯示一個班的人名字,可以獲得每個名字的學號,另外SelectedValue和SelectedItem的區別在於,SelectedItem指的是選中的那一行的對象(雖然只顯示了一列,但是實際數據可能不止一列),而SelectedValue指的是選中的特定行列的數據,比如我一個班級,每行是學生信息對象,然后DisplayMember表示姓名這一列,ValueMember表示學號這一列,如果我選中了”小王“,那么SelectedValue就是小王的學號,而SelectedItem就是指小王這個學生的信息對象。
下面是實際以代碼為例來消化這些知識點:
1)下面先舉例說明下DataGridView綁定數據的幾種方式,第一種直接添加行列:
//構造列並設置列名 dataGridView1.ColumnCount = 3; dataGridView1.Columns[0].Name = "Name"; dataGridView1.Columns[1].Name = "Age"; dataGridView1.Columns[2].Name = "ID"; //添加行 string[] row0 = { "Zhong", "18", "001" }; string[] row1 = { "Jing", "22", "002" }; dataGridView1.Rows.Add(row0); dataGridView1.Rows.Add(row1); //可以更改顯示列順序 dataGridView1.Columns[0].DisplayIndex = 1; dataGridView1.Columns[1].DisplayIndex = 0; dataGridView1.Columns[2].DisplayIndex = 2;
第二種:使用BindingSource類:
//構造數據源 BindingSource bs = new BindingSource(); Bus bus1, bus2, bus3; bs.Add(bus1 = new Bus("Benz", "Red")); bs.Add(bus2 = new Bus("BME", "Green")); bs.Add(bus3 = new Bus("Dazong", "Blue")); bus1.People.Add(new Person("Lixiaoming")); bus1.People.Add(new Person("Daming")); bus2.People.Add(new Person("xiaoli")); bus3.People.Add(new Person("linlin")); dataGridView2.DataSource = bs;
第三種指定BindingSource的DataMember,這就解釋了第二種中為什么People不能顯示的原因(雖然可以通過其他的辦法顯示出來):
//構造數據源 BindingSource bs = new BindingSource(); Bus bus1, bus2, bus3; bs.Add(bus1 = new Bus("Benz", "Red")); bs.Add(bus2 = new Bus("BME", "Green")); bs.Add(bus3 = new Bus("Dazong", "Blue")); bus1.People.Add(new Person("Lixiaoming")); bus1.People.Add(new Person("Daming")); bus2.People.Add(new Person("xiaoli")); bus3.People.Add(new Person("linlin")); dataGridView3.DataSource = bs; dataGridView3.DataMember = "People";
其中用到的公共汽車類和人類的定義如下:
/// <summary> /// 公共汽車類 /// </summary> public class Bus { private static int lastID = 0; private string _busType; private string _color; public Bus(string busType,string color) { _busType = busType; _color = color; _id = ++lastID; } private int _id; public int ID { get { return _id; } } public string Color { get { return _color; } } public string BusType { get { return _busType; } } private List<Person> _people = new List<Person>(); public List<Person> People { get { return _people; } } } public class Person { private static int lastID = 0; public Person(string name) { _name = name; _id = ++lastID; } private int _id; public int ID { get { return _id; } } private string _name; public string Name { get { return _name; } } }
這三種方式其實大同小異,還可以有很多變種,要注意的是第二種中people是沒有顯示出來的,因為其是列表結構,第三種中是直接把列表對象的people列表成員作為DataMember,這樣顯示的自然就是People中的屬性了
2)ListBox的綁定:
第一種直接添加成員,這里直接給Items添加成員。
List<string> names =new List<string>() { "xiaoxiao", "dada", "xuxu" }; listBox1.Items.AddRange(names.ToArray());
第二種也可以是直接添加成員,直接看代碼:
List<Bus> buses = new List<Bus>(); Bus bus1, bus2, bus3; buses.Add(bus1 = new Bus("Benz", "Red")); buses.Add(bus2 = new Bus("BME", "Green")); buses.Add(bus3 = new Bus("Dazong", "Blue")); bus1.People.Add(new Person("Lixiaoming")); bus1.People.Add(new Person("Daming")); bus2.People.Add(new Person("xiaoli")); bus3.People.Add(new Person("linlin")); listBox3.DataSource = buses; //這樣也可以 // listBox3.Items.AddRange(buses.ToArray()); listBox3.DisplayMember = "Color";
這種方式時先構造列表集合,但是列表中的成員不止一個成員,所以需要設置DisplayMember,列表集合也可以賦值給DataSource,達到的效果是一樣的。
第三種使用BindingSource,直接看代碼:
//構造數據源 BindingSource bs = new BindingSource(); Bus bus1, bus2, bus3; bs.Add(bus1 = new Bus("Benz", "Red")); bs.Add(bus2 = new Bus("BME", "Green")); bs.Add(bus3 = new Bus("Dazong", "Blue")); bus1.People.Add(new Person("Lixiaoming")); bus1.People.Add(new Person("Daming")); bus2.People.Add(new Person("xiaoli")); bus3.People.Add(new Person("linlin")); listBox2.DataSource = bs; listBox2.DisplayMember = "Color";
這種方式相當於在集合數據對象與控件之間建立了一個紐帶。可以看出這幾種方式基本上是差不多的
3)DataBindings.
Control的DataBindings一般用於添加控件的屬性與數據源綁定起來,以達到控件的表現形式與數據源同步。看例子:

1 Bus bus1, bus2, bus3; 2 buses.Add(bus1 = new Bus("Benz", "Red")); 3 buses.Add(bus2 = new Bus("BME", "Green")); 4 buses.Add(bus3 = new Bus("Dazong", "Blue")); 5 bus1.People.Add(new Person("Lixiaoming")); 6 bus1.People.Add(new Person("Daming")); 7 bus2.People.Add(new Person("xiaoli")); 8 bus3.People.Add(new Person("linlin")); 9 10 listBox4.DataSource = buses; 11 listBox4.DisplayMember = "Color"; 12 //控件的屬性綁定到一個列表,這里如果改變textbox1的Text,buses好像不作更改? 13 textBox1.DataBindings.Add("Text", buses, "BusType"); 14 15 mybool.Name = "hello"; 16 //控件的屬性綁定到一個對象屬性,如果在外面直接修改Text,mybool也會同步修改,如果是通過程序修改, 17 //就要執行WriteValue(); 18 textBox2.DataBindings.Add("Text", mybool, "Name");

1 class SingleClass 2 { 3 private String _name; 4 5 public String Name 6 { 7 get { return _name; } 8 set { _name = value; } 9 } 10 11 } 12 private void button8_Click(object sender, EventArgs e) 13 { 14 textBox2.Text = "BME1"; 15 textBox2.DataBindings["Text"].WriteValue(); 16 }
我這里首先把一個集合對象buses的BusType綁定到一個TextBox的Text屬性, 這個Text的屬性就會隨着選中的buses的集合元素改變而改變,但是這里有一點,如果我們修改TextBox的Text屬性,buses是得不到修改的。
而如果我們把一個對象屬性(mybool.Name)綁定到TextBox的Text屬性上,如果我們在控件中直接修改Text屬性,那么mybool這個對象也相應的變化了,如果通過代碼修改的話就要調用WriteValue()方法。
4)關於數據的同步,如果修改了其中的一個環節,其他所有環節都會有更新,見如下代碼:

1 //構造數據源 2 BindingSource bs = new BindingSource(); 3 Bus bus1, bus2, bus3; 4 bs.Add(bus1 = new Bus("Benz", "Red")); 5 bs.Add(bus2 = new Bus("BME", "Green")); 6 bs.Add(bus3 = new Bus("Dazong", "Blue")); 7 bus1.People.Add(new Person("Lixiaoming")); 8 bus1.People.Add(new Person("Daming")); 9 bus2.People.Add(new Person("xiaoli")); 10 bus3.People.Add(new Person("linlin")); 11 dataGridView2.DataSource = bs; 12 //因為Color屬性不是只讀,所以可以再控件中修改這個值,修改后,數據源就會 更新textbox3.Text 13 this.textBox3.DataBindings.Add("Text", bs, "Color");
當我們修改DataGridView的Color單元格后(綁定的對象屬性不是只讀才能修改),BindingSource也會更新,所以TextBox.Text也得到了更新。
http://files.cnblogs.com/files/monkeyZhong/DataGridViewExample.zip