对于使用Visual Basic .NET的Windows Forms中的数据绑定,我仍然很陌生,但试图熟悉它。我试图寻找这方面的信息,但无济于事。如何在DataGridView绑定时在BindingList中编辑空值?
我想建立双向一DataGridView
控制和对象的列表之间的绑定(假设他们被称为MyListElementClass
一个虚构的类型),以类似于我在this answer看到了另一个问题的方式。下面是我的实施MyListElementClass
,在一个名为MyListElementClass.vb文件:
Imports System.ComponentModel
Imports System.Runtime.CompilerServices
<Serializable>
Public NotInheritable Class MyListElementClass
Implements INotifyPropertyChanged
Implements IMyListElementClass
#Region "Fields"
Private _a As UShort
Private _b As Double
Private _c, _d, _e As Boolean
' End fields region.
#End Region
#Region "INotifyPropertyChanged implementation"
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Private Sub NotifyPropertyChanged(<CallerMemberName()> Optional ByVal propertyName As String = Nothing)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
' End INotifyPropertyChanged implementation region.
#End Region
#Region "IMyListElementClass implementation"
Public Property PropertyA As UShort Implements IMyListElementClass.PropertyA
Get
Return _a
End Get
Set(value As UShort)
If _a <> value Then
_a = value
NotifyPropertyChanged()
End If
End Set
End Property
Public Property PropertyB As Double Implements IMyListElementClass.PropertyB
Get
Return _b
End Get
Set(value As Double)
If _b <> value Then
_b = value
NotifyPropertyChanged()
End If
End Set
End Property
Public Property PropertyC As Boolean Implements IMyListElementClass.PropertyC
Get
Return _c
End Get
Set(value As Boolean)
If _c <> value Then
_c = value
NotifyPropertyChanged()
End If
End Set
End Property
Public Property PropertyD As Boolean Implements IMyListElementClass.PropertyD
Get
Return _d
End Get
Set(value As Boolean)
If _d <> value Then
_d = value
NotifyPropertyChanged()
End If
End Set
End Property
Public Property PropertyE As Boolean Implements IMyListElementClass.PropertyE
Get
Return _e
End Get
Set(value As Boolean)
If _e <> value Then
_e = value
NotifyPropertyChanged()
End If
End Set
End Property
' End IMyListElementClass implementation region.
#End Region
#Region "Constructors"
Public Sub New()
PropertyA = 0
PropertyB = 0
PropertyC = False
PropertyD = False
PropertyE = False
End Sub
Public Sub New(a As UShort, b As Double, c As Boolean, d As Boolean, e As Boolean)
Me.PropertyA = a
Me.PropertyB = b
Me.PropertyC = c
Me.PropertyD = d
Me.PropertyE = e
End Sub
Public Sub New(other As IMyListElementClass)
If other Is Nothing Then Throw New ArgumentNullException(NameOf(other))
CopyFrom(other)
End Sub
' End constructors region.
#End Region
#Region "Methods"
Public Sub CopyFrom(other As IMyListElementClass)
If other Is Nothing Then Throw New ArgumentNullException(NameOf(other))
With other
PropertyA = .PropertyA
PropertyB = .PropertyB
PropertyC = .PropertyC
PropertyD = .PropertyD
PropertyE = .PropertyE
End With
End Sub
' End methods region.
#End Region
End Class
这里的想法是,DataGridView
控制将显示的可用列表“槽”(行)认为MyListElementClass
实例可以进入到。 但是,其中一些插槽可能为空,可能需要稍后填写或清除。表中的行数由其他地方输入的数字指定,因此用户无法随时添加或删除行;他们必须与所给的空间一起工作。
我在这个当前的尝试是有结合到BindingList(Of MyListElementClass)
,其中其大小总是等于可用时隙和空的时隙的数目是由空元素表示的DataGridView
控制。但是,我发现如果我在BindingList(Of MyListElementClass)
中存在这些空值,那么这些行不能由编辑的DataGridView
控件绑定到它,我不确定如何处理这些。
的我想要在其中包含我的用户控制做一个例子,DataGridView
(这里命名为dgvDataGridView
,并已通过设计师开设专栏):
Public Class MyUserControl
Private _myBindingList As BindingList(Of MyListElementClass)
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
dgvDataGridView.AutoGenerateColumns = False ' Columns already created through the Visual Studio designer with the ordering and header text I want.
SetUpTableDataBinding()
End Sub
Private Sub SetUpTableDataBinding()
colA.DataPropertyName = NameOf(MyListElementClass.PropertyA)
colB.DataPropertyName = NameOf(MyListElementClass.PropertyB)
colC.DataPropertyName = NameOf(MyListElementClass.PropertyC)
colD.DataPropertyName = NameOf(MyListElementClass.PropertyD)
colE.DataPropertyName = NameOf(MyListElementClass.PropertyE)
Dim initialList As New List(Of MyListElementClass)(Enumerable.Repeat(Of MyListElementClass)(Nothing, 1)) ' First row will contain a null value, and hence be "empty".
_myBindingList = New BindingList(Of MyListElementClass)(initialList)
Dim source = New BindingSource(_myBindingList, Nothing)
dgvDataGridView.DataSource = source
' Some test data for data binding.
_myBindingList.AddNew() ' Adds a new MyListElementClass instance with default property values.
_myBindingList.Add(New MyListElementClass(2345, 7.4, False, True, False)) ' Just some sample values.
End Sub
End Class
这个用户控件加载后,我可以看到一个空行,一行为默认值为MyListElementClass
,并且有一行包含一些示例值,总共为三行。我可以编辑第二行和第三行,但不是第一行(我输入的任何值立即消失)。
再一次,在这个完全陌生的领域里,请耐心等待。如果我无法得到这个工作,那么我会放弃这个想法,然后回到手动设置和检索数据,就像我以前一直做的那样。
不能重播,但大多数'SetUpTableDataBinding'代码不需要。 a)你不需要创建一个List来填充一个BindingList b)你不需要一个BindingList的BindingSource。 c)DGV将从源获取列数据类型,即使这样“PropertyA”就是所有你需要的反射来获取名称。 – Plutonix
@Plutonix我在你的观点a)和b)中提到的代码是从我的问题中链接的答案开始的。我知道你可以将一个DataGridView直接绑定到一个BindingList,但我的印象是最好总是绑定到一个BindingSource(或者不是?)。为了响应c)点,我设置了每列的DataPropertyName,这样我就可以按照指定的顺序向用户显示更友好的列名,所以如果稍后更改属性名称,那么重构也会更容易。 –
'DataPropertyName'没有任何东西可以让用户看到什么。它是要绑定到的列的名称。 – Plutonix