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");

 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

时间: 2024-10-08 10:29:12

C#中数据源绑定DataSource以及相关控件(DataGridView)的使用总结的相关文章

将Excel中的数据读入到GridView控件中

使用Excel文件作为数据源,其实现的代码为: Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Server.MapPath("excel.xls") + "; Extended Properties=Excel 8.0; 实例代码: private DataSet CreateDataSource()    {        string strCon;        strCon = "Provider

[WinForm] 使用反射将业务对象绑定到窗体或控件容器

在WebForm中,可以使用反射将业务对象绑定到 ASP.NET 窗体控件.最近做Winform项目,也参考WebForm中的代码实现同样的功能.     Winform没有提供类似WebForm中的FindControl方法,我于是用遍历控件的方式,写了一个类似WebForm中的这个方法,考虑到Winform中的很多控件放在Label.TabControl中,方法采用了递归的方式.     Winform和Winform的控件也有些区别,如在Winform中,DateTimePicker取值是

XCODE中使用Main.Storyboard拉入控件并实现事件(Swift语言)

如何在XCODE中的Main.Storyboard内拉入控件并实现一个简单的效果呢?本人由于刚接触Swift语言不久,对于IDE的操作还是很生疏,不懂了就在网上参考了网上前辈们的文章.以下我将演示如何用Swift语言配合Main.Storyboard演示一个小例子,对于新建一个SingleView Application在这里就不多说了. 创建好的应用程序已经自动创建好了一个和Main.Storyboard连接好的ViewController. 接下来我们在Main.Storyboard中的Vi

iOS中UITableViewController自带的刷新控件

iOS中UITableViewController自带的刷新控件 一.引言 在iOS开发中,使用tableView的界面,大多会用到一个下拉刷新的的控件,第三方库中,我们一般会选择比较好用的MJRefresh,其实,在iOS6之后,系统为我们提供了一个原生的刷新控件,使用起来非常方便,只是制定性不强,如果我们没有复杂的需求,使用UIRefreshControl也是不错的一个选择. 二.UITableViewController 相对于UIViewController,UITableViewCon

将MenuStrip控件中的信息添加到TreeView控件中【转载】

本文详细介绍怎样将MenuStrip控件中的信息添加到TreeView控件中 首先在WinForm窗体中添加一个MenuStrip控件和TreeView控件,根据个人的爱好把控件布局好后.在窗体的加载事件中(根据自己的情况而定)添加如下的代码: /// <summary>   /// 窗体加载时事件   /// </summary>   /// <param name="sender"></param>   /// <param n

iOS中如何让TextView和TextField控件支持return键收起输入法

TextView和TextField控件是iOS中负责接收用户输入的控件,那当用户输入完成时怎么收起面板呢? 1.TextView和TextField控件获得焦点之后的第一反应就是弹出输入法面板: 2.让TextView和TextField失去焦点的方法是调用resignFirstResponder. 3.在TextView(shouldChangeTextInRange)和TextField(shouldReturn)方法中实现.

当前线程不在单线程单元中,因此无法实例化 ActiveX 控件

"/"应用程序中的服务器错误. 当前线程不在单线程单元中,因此无法实例化 ActiveX 控件"c552ea94-6fbb-11d5-a9c1-00104bb6fc1c". 说明: 执行当前 Web 请求期间,出现未经处理的异常.请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息. 异常详细信息: System.Threading.ThreadStateException: 当前线程不在单线程单元中,因此无法实例化 ActiveX 控件"

InteropBitmap指定内存,绑定WPF的Imag控件时刷新问题。

1.InteropBitmap指定内存,绑定WPF的Imag控件的Source属性 创建InteropBitmap的时候,像素的格式必须为PixelFormats.Bgr32, 如果不是的话在绑定到Image控件的Source属性,刷新新界面(BitmapSource.Invalidate())的时候会造成内存泄露. 2. 内存映射: //内存共享类 internal class Win32Mess { [DllImport("VCamBridge.dll", EntryPoint =

定时器NSTimer放在主线程中如何解决与其他UI控件的冲突

在ios应用中  当定时器NSTimer在主线程中,可能会与其他UI控件产生冲突,比如广告栏的自动滚动,比如在当前页面中有一个textView,滚动时可能会导致定时器停止,这是为什么呢? 因为同在主线程中,系统会优先处理用户的拖动,那么就造成定时器的卡住 停止现象,怎么做呢? 需要把定时器NSTimer对象 放到 RunLoop循环中,就可以解决这个问题. [[NSRunLoop mainRunLoop]addTimer: self.timer toMode:NSRunLoopCommomMod