C#中數據源綁定DataSource以及相關控件(DataGridView)的使用總結


 

我們在編程過程中,會涉及到表格數據的顯示,存儲等,就可能涉及到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");
View Code
 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         }
View Code

 

  

   我這里首先把一個集合對象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");
View Code

         當我們修改DataGridView的Color單元格后(綁定的對象屬性不是只讀才能修改),BindingSource也會更新,所以TextBox.Text也得到了更新。

 http://files.cnblogs.com/files/monkeyZhong/DataGridViewExample.zip


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM