I'm trying to use a DataSet, filled from a SQL Database, that have only one column with unique names to fill ComboBoxes with.
Right now I'm using this code:
ClassTables.FillDistrib()
ComboBox.DataSource = ClassTables.Distrib.Tables("Names")
ClassTables is a Class used to fill my DataSets.
Distrib is the name of my DataSet (FillDistrib is the Sub used to clear and fill it)
ComboBox is the name of my ComboBox
But the ComboBox droplist is left blank.
However, used in a DataGridView, it appears that the DataSet is filled correctly.
When assigning a complex object as a DataTable to the DataSource property of ComboBox or ListBox controls, specify, using the DisplayMember property, which Column of the DataTable should be used as source to display the text of the ListControl Items.
If the selected item should also return a value different from the text displayed, also set the ValueMember property to the name of the Column that provides the associated values.
Possibly, before setting the Control's DataSource reference (to avoid redundant iterations of the underlying data).
Let's build a DataTable to test the procedure:
Assign a DataTable to the DataSource of a ComboBox control, specifying as the DisplayMember the name of the Column that provides the text to display and as ValueMember the name of the Column that provides additional data that will be returned by the ComboBox.SelectedValue property when a user changes the SelectedItem:
Dim dt As New DataTable("TestTable")
dt.Columns.AddRange({
New DataColumn("Names", GetType(String)),
New DataColumn("Values", GetType(Integer))
})
Dim row As DataRow = dt.NewRow()
dt.Rows.Add({"Some Name", 1})
dt.Rows.Add({"Some OtherName Jr.", 2})
dt.Rows.Add({"Another Name", 3})
dt.Rows.Add({"Last Name", 4})
ComboBox1.DisplayMember = "Names"
ComboBox1.ValueMember = "Values"
ComboBox1.DataSource = dt
Private Sub ComboBox1_SelectionChangeCommitted(sender As Object, e As EventArgs) Handles ComboBox1.SelectionChangeCommitted
Dim cbo = DirectCast(sender, ComboBox)
TextBox1.Text = cbo.GetItemText(cbo.SelectedValue)
End Sub
Result:
Related
I have a form that upon pressing a button creates a panel inside a FlowLayoutPanel. the panel does contain other control objects as can be seen from the pic.
The problem that controls in different panels are linked together ,when in choose in combobox all others change to the same
This before any selection
After selection :
Shouldn't they be bound by their parent control which in this case will be the panel ?
I just tested what happens when you bind two ComboBox controls to the same DataTable directly and when you bind two ComboBox controls to different BindingSources that are bound to the same DataTable. I added four ComboBoxes and two BindingSources to a form and then added this code:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim table1 As New DataTable
Dim table2 As New DataTable
With table1.Columns
.Add("Id", GetType(Integer))
.Add("Name", GetType(String))
End With
With table2.Columns
.Add("Id", GetType(Integer))
.Add("Name", GetType(String))
End With
With table1.Rows
.Add(1, "One")
.Add(2, "Two")
End With
With table2.Rows
.Add(1, "First")
.Add(2, "Second")
End With
BindingSource1.DataSource = table1
BindingSource2.DataSource = table1
With ComboBox1
.DisplayMember = "Name"
.ValueMember = "Id"
.DataSource = BindingSource1
End With
With ComboBox2
.DisplayMember = "Name"
.ValueMember = "Id"
.DataSource = BindingSource2
End With
With ComboBox3
.DisplayMember = "Name"
.ValueMember = "Id"
.DataSource = table2
End With
With ComboBox4
.DisplayMember = "Name"
.ValueMember = "Id"
.DataSource = table2
End With
End Sub
When I ran the project, I saw "One" displayed in the first two ComboBoxes and "First" displayed in the last two, as expected. I was able to make a selection in either of the first two ComboBoxes without affecting the other, while making a selection in either of the last two ComboBoxes did affect the other. This is almost certainly a demonstration of the issue you're seeing and the solution to said issue. Using the same original data source is fine but you should pretty much always use a BindingSource to bind to your control(s).
If you create a user control, as I recommend you do for groups of child controls that you want to reuse, then the BindingSource object(s) can be added in the designer and used internally. You can just add a property to the control for the data source.
I have two datagridviews. One is dtgridPopulate and is populated with data from the database.
dtgridPopulate columns are (checkbox, code, name)
checkbox
code
name
checkbox icon
c1
customer_one
Then the second datagridview is dtgridGenerate which has generated values from dtgridPopulate.
I use the code dtgridPopulate.Rows.Add(code, name) to add manually the value from dtgridPopulate to dtgridGenerate.
dtgridGenerate columns are (code, name)
code
name
c1
customer_one
When I check the checkbox in the dtgridPopulate it will transfer the values (code, name) to the dtgridGenerate. But the problem is when I uncheck the checkbox in the dtgridPopulate, It should also REMOVE the values in the dtgridGenerate.
Private Sub dtgridPopulateSelectAll_CurrentCellDirtyStateChanged(ByVal sender As Object, ByVal e As EventArgs) Handles dtgridPopulate.CurrentCellDirtyStateChanged
RemoveHandler dtgridPopulate.CurrentCellDirtyStateChanged, AddressOf dtgridPopulateSelectAll_CurrentCellDirtyStateChanged
If TypeOf dtgridPopulate.CurrentCell Is DataGridViewCheckBoxCell Then
dtgridPopulate.EndEdit()
Dim Checked As Boolean = CType(dtgridPopulate.CurrentCell.Value, Boolean)
If Checked Then
code = dtgridPopulate.CurrentRow.Cells(1).Value.ToString
name = dtgridPopulate.CurrentRow.Cells(2).Value.ToString
dtgridGenerate.Rows.Add(code, name)
Else
For Each drow As DataGridViewRow In dtgridPopulate.SelectedRows 'This is for uncheck but it doens't work
dtgridGenerate.Rows.Remove(row)
Next
End If
End If
AddHandler dtgridPopulate.CurrentCellDirtyStateChanged, AddressOf dtgridPopulateSelectAll_CurrentCellDirtyStateChanged
End Sub
I refer to this reference
Error when I uncheck the checkbox: row provided does not belong to this datagridview control. parameter name: datagridviewrow
I am not sure “why” you have unsubscribed and then re-subscribed to the event. Typically, this is only needed if the code in the event “changes” something in the grid that would cause the event to re-fire and this is not happening in your current code. Nor is ending the grids edit necessary.
Also, your use of the grids CurrentCellDirtyStateChanged event has one drawback in relation to what you want to do… it will NOT re-fire if the user checks and unchecks the same cell over and over. In other words, if the user clicks a check box cell and the check box becomes checked and the event fires… then … if the user “unchecks” the same cell before clicking on any other cell, then the event will NOT refire.
Also, it looks like the event is using a different grid from the signature of the event… dtgridPopulateSelectAll_CurrentCellDirtyStateChanged … ? … “SelectAll” and the grid in the event is called… dtgridPopulate … this is confusing.
Given this, I suggest two things to help. 1) create and use an “Empty” DataTable for the second grid. This way we could simply add and remove items from that table. 2) use the grids CellContnetClick event for this. It will re-fire if the user clicks on the same cell over and over in addition to firing ONLY when the check box is changed.
So, I propose these small changes. First add a global variable named generateDT as a DataTable used as a DataSource to the second grid. Initially this table would be empty. Second use the grids CellContentClick event to make these additions and removal of the rows.
Dim generateDT As DataTable
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim dt As DataTable = New DataTable()
dt.Columns.Add("checkbox", GetType(Boolean))
dt.Columns.Add("code", GetType(String))
dt.Columns.Add("Name", GetType(String))
dt.Rows.Add(False, "c1", "customer 1")
dt.Rows.Add(False, "c2", "customer 2")
dt.Rows.Add(False, "c3", "customer 3")
dtgridPopulate.DataSource = dt
generateDT = New DataTable()
generateDT.Columns.Add("code", GetType(String))
generateDT.Columns.Add("Name", GetType(String))
dtgridGenerate.DataSource = generateDT
End Sub
Then in the cell content click event, if the clicked cell is a check box cell, then… grab the checked state and both the code and name of the clicked-on row. Then if the check box cell is checked, then simply add the code and name to the second grids global DataTable variable generateDT. If the check box is unchecked, then we will loop through each row in the second grid and if we find a match then simply remove that row from the second grids global DataTable… something like…
Private Sub dtgridPopulate_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles dtgridPopulate.CellContentClick
If e.ColumnIndex = 0 Then
Dim Checked = CType(dtgridPopulate.Rows(e.RowIndex).Cells(e.ColumnIndex).EditedFormattedValue, Boolean)
Dim code = dtgridPopulate.CurrentRow.Cells(1).Value.ToString
Dim Name = dtgridPopulate.CurrentRow.Cells(2).Value.ToString
If Checked Then
generateDT.Rows.Add(code, Name)
Else
Dim rowToRemove As DataRowView
For Each row As DataGridViewRow In dtgridGenerate.Rows
If row.Cells(0).Value.ToString() = code Then
rowToRemove = CType(row.DataBoundItem, DataRowView)
generateDT.Rows.Remove(rowToRemove.Row)
Exit For
End If
Next
End If
End If
End Sub
So i have a database with 2 rows code,name lets say its like
code / name
1 / john
2 / george
i use this query to bring them in my combo box .
strConnection = String.Format("Provider=SQLOLEDB;Data Source={0};Initial Catalog={1};User ID={2};Password={3};",
strServer, strDataBase, strUserName, strPassword)
Dim Connection As New OleDbConnection(strConnection)
Connection.Open()
Dim cm As New OleDbCommand("SELECT Codeid [Κωδικός],descr [Περιγραφή] FROM EMBONILO_B.DBO.manufacturer GROUP BY Codeid,descr", Connection)
Dim dr As OleDbDataReader = cm.ExecuteReader
While dr.Read
ComboBox.Items.Add(dr(1).ToString)
End While
dr.Close()
Connection.Close()
and it show the name john and george. What i want is when you click the combo box and you select a name i want the code to appear on the combo box lets say if its george selected i want number 2 in combo box etc.
Thanks for advance.
When you are adding items to the ComboBox you are only setting the Text property, not the Value property. ComboBox.Items.Add() should have an overload where you can do specify the Value as well when you had items in your While loop, something like ComboBox.Items.Add(dr(1).ToString(), dr(0).ToString()) or maybe ComboBox.Items.Add(New ListItem(dr(1).ToString(), dr(0).ToString())) if you are using ASP.NET WebForms for example. Either way, each list item will have separate Text and Value properties; you want to put the ID in the Value property, and you can subsequently get the selected ID in your code using ComboBox.SelectedValue or similar, depending upon the control you are using for a combobox.
My assumption is you really want to obtain the ID in code to store in a db table, not display it in the UI.
This all applies to a WinForms application.
Declare a Form level variable to hold the CodeID of the currently selected descr in the combobox.
Since GetDescriptionData is called from Form.Load the values strServer, strDatabase etc. used in the connection string, must be available at this time. If they are not available until some user input is gathered move the code to a button. .DisplayMember and .ValueMember are names of fields from the Select statement.
Separate the data access code from the user interface code. Connections and commands need to be closed and disposed. Using...End Using blocks take care of that for us.
The form level variable CurrentCodeID is set in the ComboBox.SelectedIndexChanged event.
Private CurrentCodeID As String
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim ComboDataTable = GetDescriptionData()
ComboBox1.DisplayMember = "descr"
ComboBox1.ValueMember = "Codeid"
ComboBox1.DataSource = dt
End Sub
Private Function GetDescriptionData() As DataTable
Dim dt As New DataTable
Dim strConnection = String.Format("Provider=SQLOLEDB;Data Source={0};Initial Catalog={1};User ID={2};Password={3};",
strServer, strDataBase, strUserName, strPassword)
Using Connection As New OleDbConnection(strConnection),
cm As New OleDbCommand("SELECT Codeid,descr FROM EMBONILO_B.DBO.manufacturer;", Connection)
Connection.Open()
dt.Load(cm.ExecuteReader)
End Using
Return dt
End Function
Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
CurrentCodeID = ComboBox1.SelectedValue.ToString
End Sub
I have a datagridview combo box column with Read Only property set to False.
I need to insert values to the combo box (say One, Two, Three etc.) and also I need the combo box to display a certian value stored in a variable (say dim abc as string="value")
I need the combo box to display value stored in abc when the form loads.
Please advise how to achieve these two tasks.
Thanks
Combobox-type DataGridView cells/columns are, by default, read-only (users cannot change their items). Sample code to start a DataGridView1 with a combobox-type column, populated with the values you wish:
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim curCol As DataGridViewComboBoxColumn = New DataGridViewComboBoxColumn
Dim abc As String = "value"
Dim items As List(Of String) = New List(Of String)()
items.Add("One")
items.Add("Two")
items.Add("Three")
items.Add(abc)
curCol.DataSource = items
DataGridView1.Columns.Add(curCol)
End Sub
how i can change the item of combo box that is a column of data grid view according to the combobox that is present in the form
Dim productGrid as DataGridView
Dim objProductGroup As New DataGridViewComboBoxColumn
With productGroup
.HeaderText = "ProductGroup"
.Name = "ProductGroup"
.ReadOnly = True
.Items.Add("Server")
.Items.Add("Standalone")
End With
.Columns.Add(objProductGroup)
I have to select the objProductGroup combo box as per combo box that is on the form
dim box1 as ComboBox
box1..Items.Add("Server")
box1.Items.Add("Standalone")
When i will select the box1 item Server then objProductGroup comboBox should automatically updated.
The following code will change your DataGridView's CurrentRow Column "ProductGroup" to the value you selected in box1. I am not sure if you were trying to set ALL of the rows to the value in the combobox or just the current row.
In any case, you may want to test if the CurrentRow actually has any cells. For example:
If Not productGrid.CurrentRow Is Nothing Then [Execute the value changed]
For the sake of making it work after I selected a row, this is the code I used:
Private Sub box1_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles box1.SelectedIndexChanged
productGrid.CurrentRow.Cells("ProductGroup").Value = box1.SelectedItem
End Sub