将数据从数据绑定列表框移动到未绑定列表框并返回 VB.NET

Moving Data From Databound Listbox To Unbound Listbox And Back VB.NET

所以我一直在浏览并且有很多关于如何将数据从列表框移动到列表框的解释。 我有一个列表框绑定到来自我的 SQL 服务器的源,另一个未绑定。我的目标是将数据从第一个 (LBsearch) 移动到第二个 (LBselect) 并返回。我看到有人说用 LBselect.Items.Add(LBsearch.SelectedItem) 但是它没有 return 数据而是显示 System.Data.DataRowView。我尝试了很多不同的后缀,除了 LBsearch.text 之外,都显示了这一点。然后从第一个中删除数据我一直在删除数据绑定源(PersonBindingSource) PersonBindingSource.Remove(LBsearch.SelectedItem) 但我的问题是再次添加数据。

PersonBindingSource.Add(LBselect.SelectedItem)报错:

System.InvalidOperationException: Objects added to a BindingSource's list must all be of the same type.
   at System.Windows.Forms.BindingSource.Add(Object value)
   at Project_Program.Participants.btnremoveselect_Click(Object sender, EventArgs e) in E:\Documents\Visual Studio\Project Program\Project Program\Participants.vb:line 39

PersonBindingSource.Add(PersonBindingSource.Item(LBsearch.SelectedIndex)) 报错:

System.ArgumentException: Cannot add external objects to this list.
   at System.Data.DataView.System.Collections.IList.Add(Object value)
   at System.Windows.Forms.BindingSource.Add(Object value)
   at Project_Program.Participants.btnremoveselect_Click(Object sender, EventArgs e) in E:\Documents\Visual Studio\Project Program\Project Program\Participants.vb:line 38

如有任何帮助,我们将不胜感激。谢谢


Private Sub btnaddselect_Click(sender As Object, e As EventArgs) Handles btnaddselect.Click
    If LBsearch.Items.Count > 0 Then
        MsgBox(LBsearch.Text)
        ' PersonBindingSource.Remove(PersonBindingSource.Item(LBsearch.SelectedIndex))
        LBselect.Items.Add(LBsearch.Text)
        PersonBindingSource.Remove(LBsearch.SelectedItem)

        ' filter()
    End If
End Sub

Private Sub btnremoveselect_Click(sender As Object, e As EventArgs) Handles btnremoveselect.Click
    If LBselect.Items.Count > 0 Then
        Try
            'PersonBindingSource.Add(PersonBindingSource.Item(LBsearch.SelectedIndex))
            PersonBindingSource.Add(LBselect.SelectedItem)

            MsgBox(LBselect.SelectedItem.ToString())
            LBselect.Items.Remove(LBselect.SelectedItem)
        Catch ex As Exception
            TextBox1.Text = (ex.ToString)
        End Try
        'filter()
    End If
End Sub

移动行的一个主要问题是,由于它们是 DataRow,它们在未绑定控件中显示效果不佳。如果你拉出一些有用的东西,比如名字,你将不得不重新创建 DataRow 到 return 它到 original/bound/source 控件。

这是一个问题,因为现在它是 新行,所以 DataAdpter 可能会再次将它添加到数据库中!避免这种情况的一种方法是克隆 table。另外,if/when你把它们移回去,它们会出现在列表的底部,而不是原来的位置。

有一种比复制 table 数据并将任何内容移动到任何地方更好的方法。

由于被选中的行为可以用简单的布尔值表示,因此可以对其进行编码,以便 Selected 显示在一个控件中,未选中的显示在另一个控件中。为此,需要一个新的 Selected 列。如果可能,请使用 SQL:

添加一个
' MS Access syntax 
Dim SQL = "SELECT a, b, c,..., False As Selected FROM tblFoo"

这将在您的数据中创建新列table,所有值都初始化为False。您也可以手动添加该列。

' form level vars
Private dvSource As DataView
Private dvDest As DataView
...
' set up:
' *** Add a column manually if you cant use SQL
dtSample.Columns.Add("Selected", GetType(Boolean))

' we need to loop and set the initial value for an added column
For Each r As DataRow In dtSample.Rows
    r("Selected") = False
Next
' *** end of code for adding col manually

' when the column is added from SQL, you will need:
dtSample.Columns("Selected").ReadOnly = False


' create Source DV as Selected = False
dvSource = New DataView(dtSample,"Selected=False", "",
                                DataViewRowState.CurrentRows)
' create Dest DV as Selected = True
dvDest = New DataView(dtSample, "Selected=True", "",
                                DataViewRowState.CurrentRows)
' assign DS
lbSource.DataSource = dvSource
lbSource.DisplayMember = "Name"
lbSource.ValueMember = "Id"

lbDest.DataSource = dvDest
lbDest.DisplayMember = "Name"
lbDest.ValueMember = "Id"

然后在点击事件中:

' select
CType(lbSource.SelectedItem, DataRowView).Row("Selected") = True

' deselect:
CType(lbSource.SelectedItem, DataRowView).Row("Selected") = False

这两个 DataView 对象将在 Selected 上进行反向过滤。当您更改一行的状态时,它会立即从一个行中删除并出现在另一个行中,而实际上并不是来自任何 table(或集合或控件)的 added/removed。如果您将它移回源,它将出现在 与之前相同的位置

在这种情况下,移动的任何项目的 RowState 将是 Modified,这当然是(不同于 move-to-table 方法,它们将是新行(Added) 他们不是)。

如果没有 5 或 6 个图像很难说明,但是想法:

这实际上是一种非常简单的方法,并且比涉及实际移动行的方法更经济。使用 DataViews rows/items 看起来像 他们移动到另一个 table 或控制,但他们没有,也不需要。