I'm trying to set the length of a Combo Box control in the most efficient way possible. By length, I mean the number of items in the items collection of the Combo Box control.
This is the best attempt I have:
Dim cboNew As New ComboBox
For i As Integer = 0 To cboSelection.Items.Count - 1
cboNew.Items.Add(cboSelection.Items(i))
Next
cboSelection is another Combo Box control I have, I am pretty much trying to set the length of cboSelection to cboNew with one line of code (If cboSelection has 5 items, then set cboNew to have 5 items). I feel as if I have done this before, but have forgotten how.
If you are willing to use the DataSource property, you could do something like this:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ComboBox1.DataSource = New String() {"tony", "bruce", "clark"}
ComboBox2.DataSource = ComboBox1.DataSource
End Sub
Related
I have a CheckedListBox of 10 names A to J (it's a string but here I'm just using abc), and I want to make it so that every time a user check something, the text will be shown in the listbox simultaneously. I have tried this:
For i = 0 To chklistbxDrugAvailableList.Items.Count - 1
Dim drugs As String = CType(chklistbxDrugAvailableList.Items(i), String)
If chklistbxDrugAvailableList.GetItemChecked(i) Then
listbxYourOrder.Items.Add(drugs)
End If
'drugs = nothing
Next
But when I check A,B,C the text in the Listbox got repeated like so:
A
A
B
A
B
C
I don't know why this is happening. I didn't declare drugs as an array. Even when I used the drugs = nothing, it still give repeated values.
What should I do? Sorry if this is a noob question.
Here is how I would do the whole thing:
Private Sub CheckedListBox1_ItemCheck(sender As Object, e As ItemCheckEventArgs) Handles CheckedListBox1.ItemCheck
'Clear the current ListBox contents.
ListBox1.Items.Clear()
'Get the indexes of the currently checked items.
Dim checkedIndices = CheckedListBox1.CheckedIndices.Cast(Of Integer)()
'Add the current index to the list if the item is being checked, otherwise remove it.
checkedIndices = If(e.NewValue = CheckState.Checked,
checkedIndices.Append(e.Index),
checkedIndices.Except({e.Index}))
'Get the checked items in order and add them to the ListBox.
ListBox1.Items.AddRange(checkedIndices.OrderBy(Function(n) n).
Select(Function(i) CheckedListBox1.Items(i)).
ToArray())
End Sub
or like this:
Private Sub CheckedListBox1_ItemCheck(sender As Object, e As ItemCheckEventArgs) Handles CheckedListBox1.ItemCheck
'Get the indexes of the currently checked items.
Dim checkedIndices = CheckedListBox1.CheckedIndices.Cast(Of Integer)()
'Add the current index to the list if the item is being checked, otherwise remove it.
checkedIndices = If(e.NewValue = CheckState.Checked,
checkedIndices.Append(e.Index),
checkedIndices.Except({e.Index}))
'Get the checked items in order and add them to the ListBox.
ListBox1.DataSource = checkedIndices.OrderBy(Function(n) n).
Select(Function(i) CheckedListBox1.Items(i)).
ToArray()
End Sub
The difference is that, because the second option uses data-binding, the first item in the ListBox will be selected by default.
The reason that it needs to be a bit verbose is that the ItemCheck event is raised before the item is checked or unchecked. For that reason, we need to get the currently checked items first and then either add or remove the current item, depending on whether the current item is being checked or unchecked.
EDIT:
Here's an option that doesn't require clearing the ListBox:
Private Sub CheckedListBox1_ItemCheck(sender As Object, e As ItemCheckEventArgs) Handles CheckedListBox1.ItemCheck
Dim item = CheckedListBox1.Items(e.Index)
If e.NewValue = CheckState.Checked Then
ListBox1.Items.Add(item)
Else
ListBox1.Items.Remove(item)
End If
End Sub
The issue with that is that the items will appear in the ListBox in the order you checked them, rather than the order they appear in the CheckedListBox. The other options keep the items in the same order in both lists.
If I understand your question I would this:
lstbxYourOrder.Items.Clear()
For Each l As String In chklistbxDrugAvailableList.CheckedItems
listbxYourOrder.Items.Add(l)
Next
I am building a large data entry form and want to enable or disable groups of comboboxes based on a checkbox ( if the check box gets checked, the collection of combo boxes get enabled for user input and vice versa ). I want to use collection, because the comboboxes are not always going to be in sequential order ( example : Comboboxes 1-7, then Combobox 12, then 16, and 45-57 ). A collection seems ideal.
I've built the collections, added the comboboxes, and added items to the comboboxes. All the items are there in the comboboxes when I run the Application. I can enable or disable them individually, but I can't enable/disable the comboboxes as a collection.. how can I enable or disable them as a group ?
I can get this to work if I select all the combo boxes in my form, and then run the thru list matching the names against a variable ( as an example, for boxes 1 - 56 ), but that makes using a collection redundant. I am also going to want to output the data, in the collection groups, for later use.
I've been beating my head against the wall for a day or so on this..
Declare Collection
Dim CablesCollectionBoxes As New Collection
Add Comboboxes to collection
CablesCollectionBoxes.Add(ComboBox1)
CablesCollectionBoxes.Add(ComboBox2)
CablesCollectionBoxes.Add(ComboBox3)
.
<removed for space and readability>
.
CablesCollectionBoxes.Add(ComboBox56)
I am trying modify the collection of ComboBoxes to a disabled state, but the code below won't work.
for I as integer = 1 to 56
CablesCollectionBoxes.Item(i) = Disabled
next
It DOES work if I use this, but I'm not using the collection, I am running thru ALL the comboboxes and matching names :
For i As Integer = 1 To 56
Dim clsCombo As ComboBox = DirectCast(Me.Controls.Find("ComboBox" & i.ToString(), True)(0), ComboBox)
clsCombo.Enabled = True
Next
or this
ComboBox1.Enabled = True
ComboBox2.Enabled = True
ComboBox3.Enabled = True
ComboBox4.Enabled = True
.
<removed for space and readability>
.
ComboBox56.Enabled = True
How do I access the comboboxes as a group, and change the properties ? Did I declare the collection incorrectly ?
Don't use collection. Collections are soft-deprecated. Use List(Of T)
Dim comboList As New List(Of ComboBox)()
comboList.Add(cbo1)
comboList.Add(cbo2)
comboList.Add(cbo3)
' Imports System.Linq
comboList.ForEach(Sub(cbo) cbo.Enabled = True)
This is as close as you can get.
Now, if you want to have some selective way to enable/disable or whatever, you can use Tag property to mark and then it will look like this
comboList.Where(Function(cbo) cbo.Tag IsNot Nothing AndAlso CBool(cbo.Tag)).ToList().ForEach(Sub(cbo) cbo.Enabled = True)
Be sure that the check box and the enabled property of the combos are in syn when the program starts. Use the designer.
Private ComboCollection As New List(Of ComboBox)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
BuildCBCollection()
End Sub
Private Sub BuildCBCollection()
For Each ctrl As Control In Me.Controls
If TypeOf (ctrl) Is ComboBox Then
ComboCollection.Add(CType(ctrl, ComboBox))
End If
Next
End Sub
Private Sub CheckBox1_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox1.CheckedChanged
For Each cb In ComboCollection
cb.Enabled = Not cb.Enabled
Next
End Sub
I am generating Auto Serial number in DataGridView using below code:
Public Class Form1
Dim table As New DataTable()
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
table.Columns.Add("Sl", Type.GetType("System.Int32"))
table.Columns.Add("Id", Type.GetType("System.Int32"))
table.Columns.Add("Name", Type.GetType("System.String"))
table.Columns.Add("Amount", Type.GetType("System.Int32"))
DataGridView1.DataSource = table
DataGridView1.Columns(0).ReadOnly = True
DataGridView1.Columns(2).ReadOnly = True
End Sub
Private Sub DgvRowCountChanged()
For Each dgvr As DataGridViewRow In Me.DataGridView1.Rows
dgvr.Cells(0).Value = dgvr.Index + 1
Next
End Sub
Private Sub DataGridView1_RowsAdded(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewRowsAddedEventArgs) Handles DataGridView1.RowsAdded
Me.DgvRowCountChanged()
End Sub
Private Sub DataGridView1_RowsRemoved(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewRowsRemovedEventArgs) Handles DataGridView1.RowsRemoved
Me.DgvRowCountChanged()
End Sub
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
Dim Index As Integer
If DataGridView1.RowCount > 1 Then
Index = DataGridView1.CurrentCell.RowIndex
DataGridView1.Rows.RemoveAt(Index)
End If
End Sub
End Class
Serial number appears, but when I click on next column it disappears. Why is that happening?
Do this, make life easy:
Ditch all that code
Make a new form
Add a new item of type DataSet to your project, and give it a nice name (not DataSet1)
Double click the dataset, so its design surface appears
Right click the surface, choose "Add new.. DataTable", give it a more imaginative name than DataTable1. I'll assume you choose License (serial number? name? seems licensey)
Right click the new datatable and choose "Add New.. Column"
Name the new column Sl, and use the properties grid to give it a type of System.Int32
Repeat for your other columns
Save
Open the Data Sources window on the View menu (Other Windows item)
Open the new blank form you made in step 2
Expand every node you can see in the Data Sources window
Drag the node representing your datatable (the one with an icon looking like a datagridview next toit) out of the data sources window and drop it on the form
Remove (delete) the bindingnavigator it created (you wont need it)
CLick the datagridview, CLick the small arrow that appeared in the top right of the control to show the popup menu, choose Edit Columns
Make whatever columns you want read only
Set other properties like sizes of columns, fill weights, header texts etc
Open the code of your form. add a single row of data to the datatable, in the constructor, after the initializecomponent() call:
Me.myImaginativeDataSetName.License.AddLicenseRow(1, 1, "Name Blah", 1234)
That's it. It looks like a lot because I've broken it down into the absolute step by step - about the only thing that isn't there is reminding you to take a breath every few steps because you'll be so blown away how easy it makes your life when you get the IDE to write code for you, ;)
OK, it's maybe not that exciting... But you already use the Forms designer to write reams of code for you, so this is how you leverage the other tools so you don't have to work with un-typed datasets all the time. Ugh.
The dataset this creates has a full suite of nicely named properties; don't use the basic stringy stuff ever again:
'yes - do this
For Each ro as LicenseRow in myDataSet.License
If ro.IsNameNull Then ro.Name = "Default Name" & ro.Sl
Next ro
'no - heck no
For Each ro as DataRow in myDataSet.Tables("License").Rows
If ro.IsNull("Naem") Then ro.item("Name") = "Default Name" & Convert.ToInt32(ro.Item("Sl"))
Next ro
See how much cleaner the first one is? ro.Sl is a nice Integer property, no casting or converting, no incessant Tables this or Columns/Rows that, Intellisense helps you out becaise it's all strongly named stuff, no typos in string column names like I made in the second...
It looks like youre trying to prevent the user from adding rows with this:
If DataGridView1.RowCount > 1 Then
Index = DataGridView1.CurrentCell.RowIndex
DataGridView1.Rows.RemoveAt(Index)
End If
End Sub
If so, click the datagridview on the form designer and in the properties grid set AllowUserToAddRows to false. If youre also trying to prevent deletion set the same on AllowUserToDeleteRows
The title is somewhat misleading. I can reduce the .Items Count to zero by the usual methods, but the dropdown list area keeps its former dimensions.
When adding items to ComboBox manually, I can do ComboBox.Items.Clear. The ComboBox.Items count is reduced to zero.
When databinding ComboBox, I can do ComboBox.DataSource = Nothing. Or, set the BindingSource = Nothing, if using one. The ComboBox.Items Count is reduced to zero.
However, the combobox dropdown area retains the rows it had been populated with, except that they are "empty". In other words, it's a white box which is the same height as the list it had contained.
Seems to me that if I clear a ComboBox, it ought to appear identical to one which has never been bound or filled.
The DropDownStyle = DropDownList
ComboBox before filling/binding:
ComboBox after filling/binding:
ComboBox after clearing/setting datasource/bindingsource = Nothing:
Does anyone know a way to prevent this? If I unbind or otherwise clear the ComboBox, I'd like the dropdown to then consist of one empty row, as in the first image.
Thanks.
The following should fix that:
ComboBox.DropDownStyle = ComboBoxStyle.DropDown
ComboBox.DropDownStyle = ComboBoxStyle.DropDownList
For some reason changing the 'DropDownStyle' property of the combobox to something that is not DropDownList, and then changing it back resizes the DropDownList to the minimum possible height for its entries, or at least in Visual Studio 2015 with .NET Framework 4.5. Hope this helps.
Edit: It's strange that if the ComboBox's style is ComboBoxStyle.DropDown that ComboBox.DropDownHeight = 106 will change the height, but if the style is ComboBoxStyle.DropDownList it won't. Yet another mystery of .NET!
To force reset a height of dropdown element you need to change ComboBox.DropDownStyle to some other and back to the original
Me.ComboBox1.DataSource = Nothing
Me.ComboBox1.DropDownStyle = ComboBoxStyle.DropDown
Me.ComboBox1.DropDownStyle = ComboBoxStyle.DropDownList
You must set the DropDownHeight property of the ComboBox control after clearing the DataSource. Here is an example that sets it back to a default that you can adapt for your own purposes.
Private m_intDefaultDropDownHeight As Integer = 1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim lstItems As New List(Of String)
lstItems.Add("A")
lstItems.Add("B")
lstItems.Add("C")
m_intDefaultDropDownHeight = ComboBox1.DropDownHeight
ComboBox1.DataSource = lstItems
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
ComboBox1.DataSource = Nothing
ComboBox1.DropDownHeight = m_intDefaultDropDownHeight
End Sub
So I have a listbox, filled with informations from a structure tab as follows :
Private Sub Modifier_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For i As Integer = 0 To frmConnecter.TabPolyFlix.Length - 1
ListBox1.Items.Add(frmConnecter.TabPolyFlix(i).strTitre)
Next
End Sub
And I want the user to choose to delete the TabPolyFlix(ListBox1.SelectedIndex) and it has to get updated in the original Tab and thus in the Listbox
P.S I tried this but it only updates it in the listbox, not in the original tab
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Dim Temp As New List(Of ListViewItem)
For i As Integer = 0 To ListBox1.Items.Count - 1
If ListBox1.SelectedIndices.Contains(i) = False Then
Temp.Add(ListBox1.Items(i))
End If
Next
ListBox1.Items.Clear()
For i As Integer = 0 To Temp.Count - 1
ListBox1.Items.Add(Temp(i))
Next i
End Sub
Arrays have a fixed size. Better use a List(Of ListViewItem) for TabPolyFlix. Then assign the List directly to the DataSource of the listbox:
'Fill the listbox
ListBox1.DisplayMember = "strTitre" 'You can also set this in the property grid.
ListBox1.DataSource = frmConnecter.TabPolyFlix
You can also override the ToString method of ListViewItem in order to display anything you want in the listbox and keep ListBox1.DisplayMember empty.
Now you can directly delete the item in the list:
frmConnecter.TabPolyFlix.Remove(ListBox1.SelectedItem)
or
frmConnecter.TabPolyFlix.RemoveAt(ListBox1.SelectedIndex)
or if you want to delete several items at once
For Each i As Integer In ListBox1.SelectedIndices.Cast(Of Integer)()
frmConnecter.TabPolyFlix.Remove(ListBox1.Items(i))
Next
and re-display the list:
ListBox1.DataSource = Nothing
ListBox1.DataSource = frmConnecter.TabPolyFlix
The moral of the story is: don't use controls (the ListBox in this case) as your primary data structure. Use it only for display and user interaction. Perform the logic (the so called business logic) on display-independent data structures and objects (so called business objects) and when finished, display the result.