Databinding not working with combox

Posted on 2015-01-29
Last Modified: 2015-02-02
Hi all.

I'm working on some code that is not working as I'd like. I have form1 that has a datagrid. When the end user right clicks a record in the datagrid and selects "View Details" then it opens form2 with record information. One of those fields is a combo box. When form2 opens I want it to display the selected value to equal whatever "MinQtyValue" is. Unfortunately, when form2 opens it does not show a selection. Below is my code, I also added a databinding to a textbox to make sure there was data and yes, when form2 opens the textbox shows "MinQtyValue" but the combobox does not:

sda.Fill(ds, "MinQtyValue")
            bs = New BindingSource(ds, "MinQtyValue")
            frm.txtMinQtyValue.DataBindings.Add("Text", bs, "MinQtyValue")

            sda.Fill(ds, "MinQtyValue")
            bs = New BindingSource(ds, "MinQtyValue")
            frm.cmbSetMin.DataBindings.Add("SelectedValue", bs, "MinQtyValue")

Open in new window

Thank you in advance!
Question by:printmedia
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
1 Comment
LVL 34

Accepted Solution

it_saige earned 500 total points
ID: 40580850
In order to use a combobox binding to SelectedValue, the Value *must* be a type of the object that is databound.

A quick and dirty example -

MainForm.vb -
Imports System.ComponentModel
Imports System.Runtime.CompilerServices

Public Class MainForm
	Private Sub OnLoad(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
		Globals.Technicians = New BindingList(Of Person) From _
		 { _
		   New Person() With {.ID = 1, .Name = "--- Unassigned ---"}, _
		   New Person() With {.ID = 2, .Name = "Peter"}, _
		   New Person() With {.ID = 3, .Name = "Paul"}, _
		   New Person() With {.ID = 4, .Name = "Mary"} _

		Globals.Tasks = New BindingList(Of Task) From _
		 { _
		  New Task() With {.ID = 1, .Name = "Sweep", .AssignedTo = Globals.Technicians(0)}, _
		  New Task() With {.ID = 2, .Name = "Mop", .AssignedTo = Globals.Technicians(0)}, _
		  New Task() With {.ID = 3, .Name = "Wash", .AssignedTo = Globals.Technicians(0)}, _
		  New Task() With {.ID = 4, .Name = "Dry", .AssignedTo = Globals.Technicians(0)} _

		taskSource.DataSource = Globals.Tasks
		TaskGrid.DataSource = taskSource
	End Sub

	Private Sub OnCellFormatting(ByVal sender As Object, ByVal e As DataGridViewCellFormattingEventArgs) Handles TaskGrid.CellFormatting
		If TypeOf sender Is DataGridView Then
			Dim dgv As DataGridView = DirectCast(sender, DataGridView)
			If dgv.Columns(e.ColumnIndex).Name.Equals(colAssignedOn.Name) Or dgv.Columns(e.ColumnIndex).Name.Equals(colCompletedOn.Name) Then
				Dim [date] As DateTime
				e.Value = If(DateTime.TryParse(e.Value.ToString(), [date]), If([date] <> DateTime.MinValue, [date].ToShortDateString(), "Not Set"), "Not Set")
				e.FormattingApplied = True
			ElseIf dgv.Columns(e.ColumnIndex).Name.Equals(colStatus.Name) Then
				Dim status As Status
				If TypeOf e.Value Is Status Then status = DirectCast(e.Value, Status)
				e.Value = status.GetEnumDescription()
				e.FormattingApplied = True
			End If
		End If
	End Sub

	Private Sub OnRowContextMenuStripNeeded(ByVal sender As Object, ByVal e As DataGridViewRowContextMenuStripNeededEventArgs) Handles TaskGrid.RowContextMenuStripNeeded
		If TypeOf sender Is DataGridView Then
			Dim dgv As DataGridView = DirectCast(sender, DataGridView)
			If Not dgv.SelectedRows.Contains(dgv.Rows(e.RowIndex)) Then dgv.Rows(e.RowIndex).Selected = True
			e.ContextMenuStrip = GridContextMenu
		End If
	End Sub

	Private Sub OnClick(ByVal sender As Object, ByVal e As EventArgs) Handles ViewDetailToolStripMenuItem.Click
		Dim task As Task = Nothing
		Dim editor As DetailsView = Nothing
		If TaskGrid.SelectedRows.Count = 1 Then
			task = DirectCast(TaskGrid.SelectedRows(0).DataBoundItem, Task)
			editor = New DetailsView(task)
		End If
	End Sub
End Class

Module Globals
	Public Property Technicians() As BindingList(Of Person) = New BindingList(Of Person)
	Public Property Tasks() As BindingList(Of Task) = New BindingList(Of Task)
End Module

Module Extensions
	<Extension()> _
	Public Function GetEnumDescription(ByVal Value As [Enum]) As String
		Dim _fieldInfo = Value.GetType().GetField(Value.ToString())
		Dim attributes = _fieldInfo.GetCustomAttributes(GetType(DescriptionAttribute), False)
		Return If(attributes.Length > 0, attributes(0).Description, Value.ToString())
	End Function
End Module

Public Class Task
	Public Property ID() As Integer
	Public Property Name() As String
	Public Property AssignedTo() As Person
	Public Property AssignedOn() As DateTime
	Public Property CompletedOn() As DateTime
	Public Property Status() As Status
End Class

Public Enum Status
	<Description("None")> None = 0
	<Description("Unassigned")> Unassigned
	<Description("Assigned")> Assigned
	<Description("In Progress")> InProgress
	<Description("In Research")> InResearch
	<Description("Completed")> Completed
End Enum

Public Class Person
	Public Property ID() As Integer
	Public Property Name() As String

	Public Overrides Function ToString() As String
		Return Name
	End Function
End Class

Open in new window

MainForm.Designer.vb -
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class MainForm
	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)
			If disposing AndAlso components IsNot Nothing Then
			End If
		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.TaskGrid = New System.Windows.Forms.DataGridView()
		Me.colID = New System.Windows.Forms.DataGridViewTextBoxColumn()
		Me.colName = New System.Windows.Forms.DataGridViewTextBoxColumn()
		Me.colAssignedTo = New System.Windows.Forms.DataGridViewTextBoxColumn()
		Me.colAssignedOn = New System.Windows.Forms.DataGridViewTextBoxColumn()
		Me.colCompletedOn = New System.Windows.Forms.DataGridViewTextBoxColumn()
		Me.colStatus = New System.Windows.Forms.DataGridViewTextBoxColumn()
		Me.taskSource = New System.Windows.Forms.BindingSource(Me.components)
		Me.GridContextMenu = New System.Windows.Forms.ContextMenuStrip(Me.components)
		Me.ViewDetailToolStripMenuItem = New System.Windows.Forms.ToolStripMenuItem()
		CType(Me.TaskGrid, System.ComponentModel.ISupportInitialize).BeginInit()
		CType(Me.taskSource, System.ComponentModel.ISupportInitialize).BeginInit()
		Me.TaskGrid.AllowUserToAddRows = False
		Me.TaskGrid.AllowUserToDeleteRows = False
		Me.TaskGrid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize
		Me.TaskGrid.Columns.AddRange(New System.Windows.Forms.DataGridViewColumn() {Me.colID, Me.colName, Me.colAssignedTo, Me.colAssignedOn, Me.colCompletedOn, Me.colStatus})
		Me.TaskGrid.Location = New System.Drawing.Point(13, 13)
		Me.TaskGrid.MultiSelect = False
		Me.TaskGrid.Name = "TaskGrid"
		Me.TaskGrid.ReadOnly = True
		Me.TaskGrid.RowHeadersVisible = False
		Me.TaskGrid.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect
		Me.TaskGrid.Size = New System.Drawing.Size(503, 237)
		Me.TaskGrid.TabIndex = 0
		Me.colID.DataPropertyName = "ID"
		Me.colID.HeaderText = "ID"
		Me.colID.Name = "colID"
		Me.colID.ReadOnly = True
		Me.colID.Visible = False
		Me.colName.DataPropertyName = "Name"
		Me.colName.HeaderText = "Task Name"
		Me.colName.Name = "colName"
		Me.colName.ReadOnly = True
		Me.colAssignedTo.DataPropertyName = "AssignedTo"
		Me.colAssignedTo.HeaderText = "Assigned To"
		Me.colAssignedTo.Name = "colAssignedTo"
		Me.colAssignedTo.ReadOnly = True
		Me.colAssignedOn.DataPropertyName = "AssignedOn"
		Me.colAssignedOn.HeaderText = "Assigned On"
		Me.colAssignedOn.Name = "colAssignedOn"
		Me.colAssignedOn.ReadOnly = True
		Me.colCompletedOn.DataPropertyName = "CompletedOn"
		Me.colCompletedOn.HeaderText = "Completed On"
		Me.colCompletedOn.Name = "colCompletedOn"
		Me.colCompletedOn.ReadOnly = True
		Me.colStatus.DataPropertyName = "Status"
		Me.colStatus.HeaderText = "Current Status"
		Me.colStatus.Name = "colStatus"
		Me.colStatus.ReadOnly = True
		Me.GridContextMenu.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.ViewDetailToolStripMenuItem})
		Me.GridContextMenu.Name = "GridContextMenu"
		Me.GridContextMenu.Size = New System.Drawing.Size(133, 26)
		Me.ViewDetailToolStripMenuItem.Name = "ViewDetailToolStripMenuItem"
		Me.ViewDetailToolStripMenuItem.Size = New System.Drawing.Size(132, 22)
		Me.ViewDetailToolStripMenuItem.Text = "View Detail"
		Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
		Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
		Me.ClientSize = New System.Drawing.Size(532, 262)
		Me.Name = "MainForm"
		Me.Text = "Form1"
		CType(Me.TaskGrid, System.ComponentModel.ISupportInitialize).EndInit()
		CType(Me.taskSource, System.ComponentModel.ISupportInitialize).EndInit()

	End Sub
	Friend WithEvents TaskGrid As System.Windows.Forms.DataGridView
	Friend WithEvents taskSource As System.Windows.Forms.BindingSource
	Friend WithEvents colID As System.Windows.Forms.DataGridViewTextBoxColumn
	Friend WithEvents colName As System.Windows.Forms.DataGridViewTextBoxColumn
	Friend WithEvents colAssignedTo As System.Windows.Forms.DataGridViewTextBoxColumn
	Friend WithEvents colAssignedOn As System.Windows.Forms.DataGridViewTextBoxColumn
	Friend WithEvents colCompletedOn As System.Windows.Forms.DataGridViewTextBoxColumn
	Friend WithEvents colStatus As System.Windows.Forms.DataGridViewTextBoxColumn
	Friend WithEvents GridContextMenu As System.Windows.Forms.ContextMenuStrip
	Friend WithEvents ViewDetailToolStripMenuItem As System.Windows.Forms.ToolStripMenuItem

End Class

Open in new window

DetailsView.vb -
Public Class DetailsView
	Private fTask As Task
	Private techSource As List(Of Person)

	Public ReadOnly Property Task() As Task
			Return fTask
		End Get
	End Property

	Private Sub New()
		Me.New(New Task())
	End Sub

	Public Sub New(ByRef Task As Task)
		fTask = If(Task Is Nothing, New Task(), Task)

		cmbStatus.DataSource = (From value As [Enum] In [Enum].GetValues(GetType(Status)).Cast(Of Status)() Select New With {.Display = value.GetEnumDescription(), .Value = value}).ToList()
		cmbStatus.DisplayMember = "Display"
		cmbStatus.ValueMember = "Value"

		cmbTechnicians.DataSource = (From value As Person In Globals.Technicians Select New With {.Display = value.ToString(), .Value = value}).ToList()
		cmbTechnicians.DisplayMember = "Display"
		cmbTechnicians.ValueMember = "Value"

		dtpAssignedOn.DataBindings.Add(New Binding("Text", fTask, "AssignedOn", True, DataSourceUpdateMode.OnPropertyChanged))
		dtpCompletedOn.DataBindings.Add(New Binding("Text", fTask, "CompletedOn", True, DataSourceUpdateMode.OnPropertyChanged))
		tbID.DataBindings.Add(New Binding("Text", fTask, "ID", True, DataSourceUpdateMode.OnPropertyChanged))
		tbName.DataBindings.Add(New Binding("Text", fTask, "Name", True, DataSourceUpdateMode.OnPropertyChanged))
		cmbTechnicians.DataBindings.Add(New Binding("SelectedValue", fTask, "AssignedTo", True, DataSourceUpdateMode.OnPropertyChanged))
		cmbStatus.DataBindings.Add(New Binding("SelectedValue", fTask, "Status", True, DataSourceUpdateMode.OnPropertyChanged))
	End Sub
End Class

Open in new window

DetailsView.Designer.vb -
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class DetailsView
    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)
            If disposing AndAlso components IsNot Nothing Then
            End If
        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()
		Dim lblAssignedOn As System.Windows.Forms.Label
		Dim lblCompletedOn As System.Windows.Forms.Label
		Dim lblName As System.Windows.Forms.Label
		Dim lblStatus As System.Windows.Forms.Label
		Dim Label1 As System.Windows.Forms.Label
		Dim lblID As System.Windows.Forms.Label
		Me.dtpAssignedOn = New System.Windows.Forms.DateTimePicker()
		Me.dtpCompletedOn = New System.Windows.Forms.DateTimePicker()
		Me.tbName = New System.Windows.Forms.TextBox()
		Me.cmbStatus = New System.Windows.Forms.ComboBox()
		Me.cmbTechnicians = New System.Windows.Forms.ComboBox()
		Me.tbID = New System.Windows.Forms.TextBox()
		lblAssignedOn = New System.Windows.Forms.Label()
		lblCompletedOn = New System.Windows.Forms.Label()
		lblName = New System.Windows.Forms.Label()
		lblStatus = New System.Windows.Forms.Label()
		Label1 = New System.Windows.Forms.Label()
		lblID = New System.Windows.Forms.Label()
		lblAssignedOn.AutoSize = True
		lblAssignedOn.Location = New System.Drawing.Point(12, 95)
		lblAssignedOn.Name = "lblAssignedOn"
		lblAssignedOn.Size = New System.Drawing.Size(70, 13)
		lblAssignedOn.TabIndex = 1
		lblAssignedOn.Text = "Assigned On:"
		lblCompletedOn.AutoSize = True
		lblCompletedOn.Location = New System.Drawing.Point(12, 121)
		lblCompletedOn.Name = "lblCompletedOn"
		lblCompletedOn.Size = New System.Drawing.Size(77, 13)
		lblCompletedOn.TabIndex = 3
		lblCompletedOn.Text = "Completed On:"
		lblName.AutoSize = True
		lblName.Location = New System.Drawing.Point(12, 41)
		lblName.Name = "lblName"
		lblName.Size = New System.Drawing.Size(65, 13)
		lblName.TabIndex = 7
		lblName.Text = "Task Name:"
		lblStatus.AutoSize = True
		lblStatus.Location = New System.Drawing.Point(12, 147)
		lblStatus.Name = "lblStatus"
		lblStatus.Size = New System.Drawing.Size(40, 13)
		lblStatus.TabIndex = 9
		lblStatus.Text = "Status:"
		Label1.AutoSize = True
		Label1.Location = New System.Drawing.Point(12, 68)
		Label1.Name = "Label1"
		Label1.Size = New System.Drawing.Size(69, 13)
		Label1.TabIndex = 12
		Label1.Text = "Assigned To:"
		lblID.AutoSize = True
		lblID.Location = New System.Drawing.Point(12, 15)
		lblID.Name = "lblID"
		lblID.Size = New System.Drawing.Size(21, 13)
		lblID.TabIndex = 5
		lblID.Text = "ID:"
		Me.dtpAssignedOn.CustomFormat = "MM/dd/yyyy"
		Me.dtpAssignedOn.Location = New System.Drawing.Point(95, 92)
		Me.dtpAssignedOn.Name = "dtpAssignedOn"
		Me.dtpAssignedOn.Size = New System.Drawing.Size(121, 20)
		Me.dtpAssignedOn.TabIndex = 2
		Me.dtpCompletedOn.CustomFormat = "MM/dd/yyyy"
		Me.dtpCompletedOn.Location = New System.Drawing.Point(95, 118)
		Me.dtpCompletedOn.Name = "dtpCompletedOn"
		Me.dtpCompletedOn.Size = New System.Drawing.Size(121, 20)
		Me.dtpCompletedOn.TabIndex = 4
		Me.tbName.Location = New System.Drawing.Point(95, 38)
		Me.tbName.Name = "tbName"
		Me.tbName.Size = New System.Drawing.Size(121, 20)
		Me.tbName.TabIndex = 8
		Me.cmbStatus.FormattingEnabled = True
		Me.cmbStatus.Location = New System.Drawing.Point(95, 144)
		Me.cmbStatus.Name = "cmbStatus"
		Me.cmbStatus.Size = New System.Drawing.Size(121, 21)
		Me.cmbStatus.TabIndex = 10
		Me.cmbTechnicians.FormattingEnabled = True
		Me.cmbTechnicians.Location = New System.Drawing.Point(95, 65)
		Me.cmbTechnicians.Name = "cmbTechnicians"
		Me.cmbTechnicians.Size = New System.Drawing.Size(121, 21)
		Me.cmbTechnicians.TabIndex = 11
		Me.tbID.Location = New System.Drawing.Point(95, 12)
		Me.tbID.Name = "tbID"
		Me.tbID.ReadOnly = True
		Me.tbID.Size = New System.Drawing.Size(121, 20)
		Me.tbID.TabIndex = 6
		Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
		Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
		Me.ClientSize = New System.Drawing.Size(226, 173)
		Me.Name = "DetailsView"
		Me.Text = "DetailsView"

	End Sub
	Friend WithEvents dtpAssignedOn As System.Windows.Forms.DateTimePicker
	Friend WithEvents dtpCompletedOn As System.Windows.Forms.DateTimePicker
	Friend WithEvents tbName As System.Windows.Forms.TextBox
	Friend WithEvents cmbStatus As System.Windows.Forms.ComboBox
	Friend WithEvents cmbTechnicians As System.Windows.Forms.ComboBox
	Friend WithEvents tbID As System.Windows.Forms.TextBox
End Class

Open in new window

Produces the following output -Initial startup.Right-clicking on a row will select if (if not selected) and bring up the context menu.Let's change the Status to Completed.Status update on the DetailView and the datagrid simultaneously.That being said, I have noticed some erroneous behaviour when you initially start-up the form and try to do the same with the last (and sometimes second to last row).  It will show the changes once you close the detail form and choose another row (if you go back to the last row and alter it again both forms show the change immediately).  The issue with updating the grid is easily solved by refreshing the binding source when you exit the detail view.


Featured Post

Creating Instructional Tutorials  

For Any Use & On Any Platform

Contextual Guidance at the moment of need helps your employees/users adopt software o& achieve even the most complex tasks instantly. Boost knowledge retention, software adoption & employee engagement with easy solution.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
visual studio windows onkeyup 2 40
Best book for Internet security 4 55
GUID's in SQL Server 4 31
Subtract dates in 6 35
This tutorial demonstrates one way to create an application that runs without any Forms but still has a GUI presence via an Icon in the System Tray. The magic lies in Inheriting from the ApplicationContext Class and passing that to Application.Ru…
Creating an analog clock UserControl seems fairly straight forward.  It is, after all, essentially just a circle with several lines in it!  Two common approaches for rendering an analog clock typically involve either manually calculating points with…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

751 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question