我想我很清楚BindingSource类的作用 - 即在数据源和UI控件之间提供一个间接层.它实现了IBindingList接口,因此也提供了对排序的支持.而且我经常使用它,没有太多问题.但我想知道我是否经常使用它而不是我应该使用它.也许一个例子会有所帮助.
假设我在表单上只有一个简单的文本框(使用WinForms),我想将该文本框绑定到返回字符串的类中的简单属性.在这种情况下使用BindingSource值得吗?
现在让我说我的表单上有一个网格,我想将它绑定到DataTable.我现在应该使用BindingSource吗?
在后一种情况下,我可能不会使用BindingSource作为DataTable从我可以收集的内容中提供与BindingSource本身相同的功能.当添加,删除行等时,DataTable将触发正确的事件,以便网格自动更新.
但是在第一种情况下,文本框被绑定到一个字符串,我可能会让包含字符串属性的类实现INotifyPropertyChanged,这样它就可以在字符串更改时触发PropertyChanged事件.我会使用BindingSource,以便它可以监听这些PropertyChanged事件,以便它可以在字符串更改时自动更新文本框.
到目前为止这听起来怎么样?我仍然觉得我的理解存在差距,这使我无法看到整体情况.到目前为止,这是一个非常模糊的问题,所以我会尝试提出一些更具体的问题 - 理想情况下,答案会引用上面的例子或类似的东西......
(1)在上述任何一个例子中是否值得使用BindingSource?
(2)似乎开发人员只是"假设"DataTable类在正确的时间触发PropertyChanged事件时会做正确的事情.如何知道数据源是否能够执行此操作?是否存在数据源应该实现的特定接口,以便开发人员能够承担此行为?
(3)在考虑是否使用BindingSource时,控制绑定的是否重要?或者只是影响决策的数据源?也许答案是(这看起来足够合乎逻辑):Control需要足够智能以监听PropertyChanged事件,否则需要BindingSource.那么如何判断Control是否能够做到这一点呢?同样,开发人员可以寻找控件必须实现的特定接口吗?
正是这种困惑在过去导致我总是使用BindingSource.但是我想更好地理解何时使用它,所以我只在必要时这样做.
我有一个BindingSource我在winforms数据绑定中使用的东西,我想在用户尝试在对数据进行更改后关闭表单时提供某种提示.有点"你确定要退出而不保存更改吗?"
我知道,我可以通过这样做BindingSource的CurrencyManager.ItemChanged通过只是翻转'改变’布尔事件.
但是,我想要一个更强大的功能. 我想知道当前数据何时与原始数据不同. 该事件只是告诉我是否有些事情发生了变化.用户仍然可以更改属性,点击撤消,我仍然认为要保存的数据有变化.
我想模仿记事本的这种类似功能
如果这是不可能的,那么我应该使用ItemChanged上面概述的事件处理程序还是有更好的方法?
为了记录,我正在寻找类似的东西
bool HasChanged()
{
return this.currentState != this.initialState;
}
Run Code Online (Sandbox Code Playgroud)
不是这个
bool HasChanged()
{
// this._hasChanged is set to true via event handlers
return this._hasChanged;
}
Run Code Online (Sandbox Code Playgroud)
我只是不需要自己管理当前状态和初始状态,我正在寻找一种方法来获取信息,BindingSource 如果我可以从BindingSource它的方式获得此功能更理想,因为我将能够使用许多不同数据源的功能,无论类型如何等.
我正在尝试创建一个DataGridTableStyle对象,以便我可以控制DataGrid的列宽.我创建了一个绑定到List的BindingSource对象.实际上,它通过以下方式绑定到通过Linq创建的匿名类型列表(为了清楚我正在做的事情,变量名称已更改):
List<myType> myList = new List<myType>(someCapacity);
.
...populate the list with query from database...
.
var query = from i in myList
select new
{
i.FieldA,
i.FieldB,
i.FieldC
};
myBindingSource.DataSource = query;
myDataGrid.DataSource = myBindingSource;
Run Code Online (Sandbox Code Playgroud)
然后我创建一个DataGridTableStyle对象并将其添加到datagrid.但是,它永远不会应用我设置的表格样式属性,因为我似乎无法设置正确的myDataGridTableStyle.MappingName属性.
我在谷歌搜索了大约1/2个小时,并且在一堆不同的论坛中一直看到相同问题的链接(字面意思是相同的文字,就像有人刚刚复制并粘贴了问题......我讨厌那个......) .无论如何,没有一个建议有效,就像那个人在所有其他网站上说的那样.
那么有谁知道我需要设置MappingName属性,以使我的TableStyle实际上正常工作?我在哪里可以从中获取名称?(它不能为空......只适用于绑定到DataTable或SqlCeResultSet等的BindingSource).
我认为这可能是一个问题,我使用Linq创建一个匿名的,更专业的对象版本,只有我需要的字段.我应该尝试将BindingSource直接绑定到List对象吗?或者甚至可以将DataGrid直接绑定到List对象并完全跳过绑定源.
谢谢
PS - C#,Compact Framework v3.5
更新:
我在下面发布了一个解决了我的问题的答案.无论它是否是最好的方法,它确实有效.值得一看,如果你遇到同样的问题.
c# datagrid compact-framework bindingsource datagridtablestyle
我可以通过设置DataSource属性直接将我的DataGridView控件绑定到我的业务对象的绑定列表.我的业务对象实现了INotifyPropertyChanged,因此当新项目添加到绑定列表或更新现有项目时,DGV会更新.
关于处理单个记录,我可以将业务对象绑定到文本框和其他相关控件.
我也可以从BindingList派生并创建一个CustomBindingList类来实现IBindable所需的方法,如下面的链接所述:http: //msdn.microsoft.com/en-us/library/aa480736.aspx
或者,我见过人们建议使用BindingSource.BindingSource的Datasource是业务对象,DGV的DataSource是BindingSource.
无论如何,基于BindingSource并不能为我提供:
那么,为什么推荐BindingSource方法呢?
更广泛的图片:OOPS概念和C#的新手.使用数据库应用程序.的WinForms.到目前为止只使用了DataSet/DataTable方法.现在尝试创建和使用我自己的自定义类.
通常具有主/明细表格.当我单击DGV中的Detail行时,我想在单独的窗口中编辑该记录.所以我需要处理DGV中该行所代表的列表项.试图找到一个解决方案,这让我想到了这一点和这个疑问.
鉴于我想做什么,哪种方法更好,为什么?
这里的一些指示确实会有所帮助,因为我对此非常陌生.
我刚刚通过Visual Studio 2008学习C#?
我想知道数据库,数据集和绑定源之间究竟有什么关联?
同样,表适配器的功能是什么?
我想DataGridView在Windows窗体应用程序中显示自定义集合.此自定义集合实现ICollection,和IEnumerable.我已经设置了一个BindingSource,使用该集合作为.DataSource属性.将DataGridView被设置为使用我的BindingSource,因为它的数据源.当我使用该BindingSource.Add()方法向集合添加新项目时,使用DataGridView新项目正确更新.该BindingSource数据源,在另一方面,没有:
MyCustomCollection myCollection = new MyCustomCollection();
myCollection.Add(myCustomObject1);
myCollection.Add(myCustomObject2);
myBindingSource.DataSource(myCollection);
myBindingSource.Add(myCustomObject3);
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,myBindingSource的内部List包含正确的记录数(3),并且DataGridView还包含三个记录,但myCollection只包含两个记录.我知道更改底层myCollection不会更新BindingSource或者DataGridView,因为它不是a BindingList<T>,但我认为BindingSource直接更新a 会确保myCollection同时更新.
有没有办法使用不是a的集合,BindingList<T>并在与BindingSource直接交互时更新?
更新:我在所有部分(Collection,BindingSource,DataGridView)上更新数据的一种方法如下:
myCollection.Add(myCustomObject3);
myBindingSource.DataSource = null;
myBindingSource.DataSource = myCollection;
Run Code Online (Sandbox Code Playgroud)
我很确定有更好的方法可以解决这个问题,但这是我生成预期结果的唯一方法.
我想DataGridView在Windows窗体应用程序中显示一个人员列表.我希望我的服务层返回Person对象列表(例如IList<Person>).我希望列表中的更改能够反映在其中DataGridView,反之亦然.我的理解是使用BindingSource便利的工作DataGridView.我的问题是双向数据绑定工作,我需要:
//pseudo code
BindingSource.DataSource = IBindingList<Person>
Run Code Online (Sandbox Code Playgroud)
或者我可以这样做:
BindingSource.DataSource = IList<Person>
Run Code Online (Sandbox Code Playgroud)
有什么不同?如果我的列表更改将以DataGridView任何方式更新?如果我必须使用BindingList它,似乎有点不稳定(因为创建一个依赖)BindingList从我的服务层返回一个,有没有办法解决这个问题?
微软称BindingList(在备注部分)
http://msdn.microsoft.com/en-us/library/ms132679.aspx:
"但是,典型的解决方案程序员将使用提供数据绑定功能的类,例如
BindingSource,而不是直接使用BindingList<T>."
我有一个UserControl有多个字段,我想绑定到BindingSource.我还希望UserControl公开一些BindingSource属性,以便它可以放在Form上并绑定到表单上的BindingSource.是否有捷径可寻?我意识到我可以在其BindSource setter中重新绑定UserControl的所有控件.但这似乎是错误的.是否有一些BindingSource代理可以让我将用户控件中的BindingSource链接到表单中的BindingSource?
您可以使用BindingSource的Filter属性来执行类似过滤的SQL.例如:
bindingSource.Filter= "Activated = 1"
Run Code Online (Sandbox Code Playgroud)
是否有类似文档的确切语法?
我想检查字段是否不是DBNull,所以我尝试了"Field!= NULL"但它给出了语法错误.
如果我通过设置DataSourceUpdateMode = Never来关闭绑定数据源的自动更新然后使用按钮来更新整个批次(使用binding.WriteValue),则会出现问题 - 即,仅更新第一个绑定控件的数据源.所有其他控件将重置为原始值.
这是因为当当前对象发生更改时(如上面的WriteValue之后),如果ControlUpdateMode = OnPropertyChange,则所有其他控件都会重新读取数据源中的值.
避免这个问题的标准方法是什么?
一种方法是从BindingSource派生一个类并添加一个WriteAllValues方法.此方法执行以下操作:
(1)对于每个Binding,保存ControlUpdateMode
(2)对于每个Binding,设置ControlUpdateMode = Never
(3)对于每个Binding,调用WriteValue方法
(4)对于每个Binding,将ControlUpdateMode重置为保存的值
(5)对于每个Binding,如果ControlUpdateMode = OnPropertyChange,则调用ReadValue方法.
你能看到这样做有什么问题吗?
如果使用自己的类,实现IEditableObject会解决问题吗?
在我正在研究的另一个控件中,我实现了自己的绑定.我解决这个问题的方法是使用以下代码.(我已经把它放在最低限度,我希望你能遵循它!):
Private Shared ControlDoingExplicitUpdate As MyCustomControl = Nothing
Private Sub UpdateDataSourceFromControl(ByVal item As Object, ByVal propertyName As String, ByVal value As Object)
Dim p As PropertyDescriptor = Me.props(propertyName)
Try
ControlDoingExplicitUpdate = Me
p.SetValue(item, value)
Catch ex As Exception
Throw
Finally
ControlDoingExplicitUpdate = Nothing
End Try
End Sub
Private Sub DataBindingSource_CurrentItemChanged(ByVal sender As Object, ByVal e As System.EventArgs)
If (ControlDoingExplicitUpdate …Run Code Online (Sandbox Code Playgroud) bindingsource ×10
c# ×7
winforms ×7
.net ×4
data-binding ×4
bindinglist ×2
collections ×1
database ×1
datagrid ×1
datagridview ×1
dataset ×1
filter ×1
vb.net ×1