I want one listbox on a vb.net form to display records in a datatable that have "Selected = 0" (note: "Selected is a field in the datatable) and another listbox on the form to display records in the datatable that have "Selected = 1". I wrote the posted code, but when I set the filter for bs2 it appears to affect both listboxes, even though the first listbox's datasource is bs1. Why does this happen, and how can I set a different filter for each listbox?
Private Sub SelectItems_Load(sender As Object, e As EventArgs) Handles MyBase.Load Dim cn As New SqlConnection(strConn) Dim SQL As String SQL = "SELECT UserId As Id, FullName As Name, 0 As Selected FROM Users WHERE Terminated = 0" Using da As New SqlDataAdapter(SQL, cn) da.Fill(dt) End Using bs1.DataSource = dt bs1.Sort = "Name" bs1.Filter = "Selected = 0" lbxUnSelectedItems.DataSource = bs1 lbxUnSelectedItems.ValueMember = "Id" lbxUnSelectedItems.DisplayMember = "Name" bs2.DataSource = dt bs2.Sort = "Name" bs2.Filter = "Selected = 1" lbxSelectedItems.DataSource = bs2 lbxSelectedItems.ValueMember = "Id" lbxSelectedItems.DisplayMember = "Name" cn = Nothing End Sub
Exactly what Shaun stated. Here is a simple proof of concept:
Form1.vb -
Imports System.Runtime.CompilerServicesImports System.ComponentModelPublic Class Form1 Private table1 As DataTable = Nothing Private table2 As DataTable = Nothing Private Sub OnLoad(sender As Object, e As EventArgs) Handles MyBase.Load If table1 IsNot Nothing Then table1.Dispose() If table2 IsNot Nothing Then table2.Dispose() table1 = (From i In Enumerable.Range(0, 20) Select New With {.ID = i, .Name = String.Format("Name{0}", i), .Selected = i Mod 2 = 0}).ConvertToDataTable() table2 = (From i In Enumerable.Range(0, 20) Select New With {.ID = i, .Name = String.Format("Name{0}", i), .Selected = i Mod 2 = 0}).ConvertToDataTable() BindingSource1.DataSource = table1 BindingSource2.DataSource = table1 ListBox1.DataSource = BindingSource1 ListBox1.ValueMember = "ID" ListBox1.DisplayMember = "Name" ListBox2.DataSource = BindingSource2 ListBox2.ValueMember = "ID" ListBox2.DisplayMember = "Name" End Sub Private Sub OnClick(sender As Object, e As EventArgs) Handles Button1.Click If BindingSource2.DataSource Is table1 Then BindingSource2.DataSource = table2 Else BindingSource2.DataSource = table1 End If If Not String.IsNullOrWhiteSpace(TextBox1.Text) Then BindingSource1.Filter = TextBox1.Text If Not String.IsNullOrWhiteSpace(TextBox2.Text) Then BindingSource2.Filter = TextBox2.Text End Sub Private Sub OnValidated(sender As Object, e As EventArgs) Handles TextBox2.Validated, TextBox1.Validated If Typeof sender Is TextBox Then Dim tb = DirectCast(sender, TextBox) If Not String.IsNullOrWhiteSpace(tb.Text) Then If tb.Equals(TextBox1) Then BindingSource1.Filter = tb.Text ElseIf tb.Equals(TextBox2) Then BindingSource2.Filter = tb.Text End If End If End If End SubEnd ClassModule Extensions <Extension()> _ Public Function ConvertToDataTable(Of T)(ByVal source As IEnumerable(Of T)) As DataTable Dim properties As PropertyDescriptorCollection = TypeDescriptor.GetProperties(GetType(T)) Dim table As DataTable = New DataTable() For i As Integer = 0 To properties.Count - 1 Dim [property] As PropertyDescriptor = properties(i) If [property].PropertyType.IsGenericType AndAlso [property].PropertyType.GetGenericTypeDefinition().Equals(GetType(Nullable)) Then table.Columns.Add([property].Name, [property].PropertyType.GetGenericArguments()(0)) Else table.Columns.Add([property].Name, [property].PropertyType) End If Next Dim values(properties.Count - 1) As Object For Each item As T In source For i As Integer = 0 To properties.Count - 1 values(i) = properties(i).GetValue(item) Next table.Rows.Add(values) Next Return table End FunctionEnd Module
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _Partial Class Form1 Inherits System.Windows.Forms.Form 'Form overrides dispose to clean up the component list. <System.Diagnostics.DebuggerNonUserCode()> _ Protected Overrides Sub Dispose(ByVal disposing As Boolean) Try If disposing AndAlso components IsNot Nothing Then components.Dispose() End If Finally MyBase.Dispose(disposing) End Try End Sub 'Required by the Windows Form Designer Private components As System.ComponentModel.IContainer 'NOTE: The following procedure is required by the Windows Form Designer 'It can be modified using the Windows Form Designer. 'Do not modify it using the code editor. <System.Diagnostics.DebuggerStepThrough()> _ Private Sub InitializeComponent() Me.components = New System.ComponentModel.Container() Me.ListBox1 = New System.Windows.Forms.ListBox() Me.ListBox2 = New System.Windows.Forms.ListBox() Me.Label1 = New System.Windows.Forms.Label() Me.Label2 = New System.Windows.Forms.Label() Me.TextBox1 = New System.Windows.Forms.TextBox() Me.TextBox2 = New System.Windows.Forms.TextBox() Me.Button1 = New System.Windows.Forms.Button() Me.BindingSource1 = New System.Windows.Forms.BindingSource(Me.components) Me.BindingSource2 = New System.Windows.Forms.BindingSource(Me.components) CType(Me.BindingSource1, System.ComponentModel.ISupportInitialize).BeginInit() CType(Me.BindingSource2, System.ComponentModel.ISupportInitialize).BeginInit() Me.SuspendLayout() ' 'ListBox1 ' Me.ListBox1.FormattingEnabled = True Me.ListBox1.Location = New System.Drawing.Point(13, 13) Me.ListBox1.Name = "ListBox1" Me.ListBox1.Size = New System.Drawing.Size(200, 238) Me.ListBox1.TabIndex = 0 ' 'ListBox2 ' Me.ListBox2.FormattingEnabled = True Me.ListBox2.Location = New System.Drawing.Point(219, 13) Me.ListBox2.Name = "ListBox2" Me.ListBox2.Size = New System.Drawing.Size(200, 238) Me.ListBox2.TabIndex = 1 ' 'Label1 ' Me.Label1.AutoSize = True Me.Label1.Location = New System.Drawing.Point(12, 261) Me.Label1.Name = "Label1" Me.Label1.Size = New System.Drawing.Size(32, 13) Me.Label1.TabIndex = 2 Me.Label1.Text = "Filter:" ' 'Label2 ' Me.Label2.AutoSize = True Me.Label2.Location = New System.Drawing.Point(219, 260) Me.Label2.Name = "Label2" Me.Label2.Size = New System.Drawing.Size(32, 13) Me.Label2.TabIndex = 3 Me.Label2.Text = "Filter:" ' 'TextBox1 ' Me.TextBox1.Location = New System.Drawing.Point(50, 258) Me.TextBox1.Name = "TextBox1" Me.TextBox1.Size = New System.Drawing.Size(163, 20) Me.TextBox1.TabIndex = 4 ' 'TextBox2 ' Me.TextBox2.Location = New System.Drawing.Point(257, 257) Me.TextBox2.Name = "TextBox2" Me.TextBox2.Size = New System.Drawing.Size(162, 20) Me.TextBox2.TabIndex = 5 ' 'Button1 ' Me.Button1.Location = New System.Drawing.Point(13, 292) Me.Button1.Name = "Button1" Me.Button1.Size = New System.Drawing.Size(406, 23) Me.Button1.TabIndex = 6 Me.Button1.Text = "Change Data Sources" Me.Button1.UseVisualStyleBackColor = True ' 'Form1 ' Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font Me.ClientSize = New System.Drawing.Size(436, 327) Me.Controls.Add(Me.Button1) Me.Controls.Add(Me.TextBox2) Me.Controls.Add(Me.TextBox1) Me.Controls.Add(Me.Label2) Me.Controls.Add(Me.Label1) Me.Controls.Add(Me.ListBox2) Me.Controls.Add(Me.ListBox1) Me.Name = "Form1" Me.Text = "Form1" CType(Me.BindingSource1, System.ComponentModel.ISupportInitialize).EndInit() CType(Me.BindingSource2, System.ComponentModel.ISupportInitialize).EndInit() Me.ResumeLayout(False) Me.PerformLayout() End Sub Friend WithEvents ListBox1 As System.Windows.Forms.ListBox Friend WithEvents ListBox2 As System.Windows.Forms.ListBox Friend WithEvents Label1 As System.Windows.Forms.Label Friend WithEvents Label2 As System.Windows.Forms.Label Friend WithEvents TextBox1 As System.Windows.Forms.TextBox Friend WithEvents TextBox2 As System.Windows.Forms.TextBox Friend WithEvents Button1 As System.Windows.Forms.Button Friend WithEvents BindingSource1 As System.Windows.Forms.BindingSource Friend WithEvents BindingSource2 As System.Windows.Forms.BindingSourceEnd Class
Initial load:Setting the filter for the first listbox:Now setting the filter for the second listbox:If we click the 'Change Data Sources' button to use separate datasources:
-saige-
Declan Basile
ASKER
Excellent! That's exactly what I needed to know. Thank you.
Exactly what Shaun stated. Here is a simple proof of concept:
Form1.vb -
Open in new window
Form1.Designer.vb -Open in new window
Produces the following output -Initial load:
-saige-