1.引言
BindingSource组件是数据源和控件间的一座桥,同时提供了大量的API和Event供我们使用。使用这些API我们可以将Code与各种具体类型数据源进行解耦;使用这些Event我们可以洞察数据的变化。
2.简单绑定
DataTable myTable = myTableAdapter.GetData();
//创建Table
BindingSource myBindingSource=
new
BindingSource();
//创建BindingSource
DataGridView myGrid =
new
DataGridView();
//创建GridView
myGrid.DataSource = myBindingSource;
//将BindingSource绑定到GridView
myTable;
//绑定数据到BindingSource
注:
1)绑定到DataTable,其实是绑定到DataTable提供的DataView上。每个DataTable都有一个缺省的DataView
2)DataView是绑定的实质,正如其名,它是DataTable的数据的展现。因此可以对同一个DataTable
,构建多个DataView,进而可以对这同样的数据实施不同的过滤、排序等方法,从不同侧面展示DataTable。这也体现了一定的MVC思想。
3)BindingSouce也可作为数据(其实是数据引用)的容器在不同窗体间传递,从而实现在弹出窗体中对数据的编辑
3.主细表
image
以上图所示数据为例:
1)DataSet:myDataSet
2)DataTable:ParentTable、ChildTable、GrandChildTable
3)Relation:FK_Parent_Child、FK_Child_GrandChild
//绑定父数据
parentBindingSource.DataSource = myDataSet;
parentBindingSource.DataMember =
"ParentTable"
;
m_GrandParentGrid.DataSource = m_GrandParentBindingSource;
//绑定子数据。
childBindingSource.DataSource = parentBindingSource;
//绑定到“父BindingSource”,而不是父Table
childBindingSource.DataMember =
"FK_Child_GrandChild"
;
//绑定到“父-子Relation”
//绑定孙子数据。
grandChildBindingSource.DataSource = childBindingSource;
//绑定到“子BindingSource”
grandChildBindingSource.DataMember =
"FK_Child_GrandChild"
;
//绑定到“子-孙Relation”
这样你就可以在Form上摆上3个DataView,分布绑定到这3个BindingSouce,很容易就实现了主细表关联展现。
4.数据操纵
要操纵数据,首先需要获取当前数据项。BindingSource的Current属性返回DataRowView类型的对象(就像DataView是对
DataTable的封装一样,DataRowView是对DataRow的封装),它是对当前数据项的封装,可以通过类型转换变成你想要的对象。
DataRowView currentRowView = myBindingSource.Current;
//获取当前RowView
CustomersRow custRow = currentRowView.Row
as
CustomersRow;
//类型转换为当前数据项
string
company = custRow.CompanyName;
//使用当前数据项
string
phoneNo = custRow.Phone;
5.用BindingSource做数据容器
BindingSource还可以用作数据容器,即便它没有绑定到数据源上,它内部有一个可以容纳数据的list。
5.1Add方法
调用Add方法会在BindingSource的list中插入数据项。如果这时第一次插入数据,并且没有绑定数据,那么插入数据的类型就决定了今后此list中数据的类型。
注:
1)此时再插入其它类型对象会抛出InvalidOperationException异常
2)设置DataSource属性时会刷新list,造成Add方法添加到list中的数据丢失
5.2AddNew方法
private
void
OnAddingNew(
object
sender, AddingNewEventArgs e)
{
e.NewObject =
new
MyCustomObject();
//
}
6.用BindingSource对数据排序、过滤、搜索
6.1 Sort
myBindingSource.Sort =
"ContactName ASC"
;
//对ContanctName列按ASC进行排序
myBindingSource.Sort =
"Region ASC, CompanyName DESC"
//先按Region、再按CompanyName排序
6.2 Find
Find方法根据指定属性和关键字进行查找,并返回第一个匹配对象的Index
int
index = m_CustomersBindingSource.Find(
"CompanyName"
,IBM);
//按CompanyName查找IBM
if
(index != -1)
{
myBindingSource.Position = index;
//定位BindingSource
}
6.3 Filter
m_CustomersBindingSource.Filter =
"Country = 'Germany'"
;
//过滤出Country属性为Germany的数据
7.用Event监控数据
7.1 Event
1)AddingNew
调用AddNew()方法时触发。
2)BindingComplete
当控件完成数据绑定时触发,说明控件已经从数据源中读取当前数据项的值。当BindingSource重新绑定或当前数据项改变时,会触发此事件
注:
* 当有多个控件绑定到同一数据源时,这个事件会触发多次
3)CurrrentChanged
当前数据项改变时触发此事件。触发此事件的情况如下
* Position属性改变时
* 添加、删除数据时
* DataSource或DataMember属性改变时
4)CurrentItemChanged
当前数据项的值改变时触发
5)DataError
通常输入无效数据时,由CurrencyManage抛出异常,从而触发此事件。
6)PositionChanged
Position属性改变时触发此事件。
7)ListChanged
数据集合改变时触发。触发此事件的情况如下
* adding, editing, deleting, 或 moving 数据项时
改变那些会影响List行为特征的属性时,如AllowEdit属性
* 替换List时(绑到新数据源)
8.限制数据修改
* 对于DateTime、Image等类型的数据,它们存储的格式与显示要求并不一致。
* 有时,你并不想显示客户ID,而是希望显示客户名称
* 数据库中的Null值
9.1 Binding类
DataTable table = customersDataSet.Customers;
//将TextBox的Text属性Binding到table的CustomerID列
customerIDTextBox.DataBindings.Add(
"Text"
, table,
"CustomerID"
,
true
);
//上面一行代码等同下面两行代码
Binding customerIDBinding =
new
Binding(
"Text"
, table,
"CustomerID"
,
true
);
customerIDTextBox.DataBindings.Add(customerIDBinding);
* 从数据源取数据,并按照控件要求的数据类型对此数据进行格式化(Formatting),然后传给控件
* 从控件取数据,并按照数据源的数据类型要求对此数据进行解析(Parsing),然后返回给数据源
* 自动对数据进行格式转换
9.2Binding类构造函数和属性
1)formattingEnabled(属性FormattingEnabled)
o
true
,Binding对象自动在数据源类型和控件要求的类型间进行转换
o
false
,反之
2)dataSourceUpdateMode
决定控件上数值的改变在何时提交回数据源
3)nullValue
DBNull、
null
和Nullab<T>对应的值。
4)formatString
格式转换
5)formatInfo
一个实现IFormatProvider接口的对象引用,用来自定义格式转换
要了解类型如何转换的,请学习Type Conversions and Format Providers相关内容。关于上面属性的应用,请看下面介绍
9.3基于Binding类的内置机制(属性、参数)进行类型转换
通过Binding类构造时的参数,或属性设置,可以控制它进行类型转换的机制。
1)DateTime
下面先介绍一个DateTime类型的例子,使用DateTimePicker控件
//创建Binding,设置formattingEnabled为true
birthDateTimePicker.DataBindings.Add(
"Value"
,m_EmployeesBindingSource,
"BirthDate"
,
true
);
//设定为使用自定义格式
birthDateTimePicker.Format = DateTimePickerFormat.Custom;
//设定格式
birthDateTimePicker.CustomFormat =
"MM/dd/yyyy"
;
2)Numeric
salaryTextBox.DataBindings.Add(
"Text"
, employeesBindingSource,
"Salary"
,
|