Cannot Fully Clear the Items from a Winforms ComboBox - vb.net

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

Related

How to add a form2 control on top of a form1.control

I have two forms. Form1 with richtextbox and form2 with listbox.
I'd like to put listbox on top of richtextbox, docking it.
I want to do exactly like this:
form2.Controls.Remove(ListBox1)
form2.hide
form1.richtextbox1.controls.add(form2.listbox1)
form1.richtextbox1.hide 'I can't hide, also listbox will hide...
form2.listbox1.location= richtextbox1 or
form2.listbox1.bounds=richtextbox1.bounds
Everything works until setting form2.listbox1.location as If richtextbox1 is hidden also listbox will be. Also, setting location and/or bounds of listbox the same as richtextbox is not completely covering the richtextbox. I also tried using the same size for both.
Gif Example
This works for me:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim LB As ListBox = Form2.ListBox1
If IsNothing(LB.Tab)
LB.Tag = LB.Size ' <-- store it for later use
End If
Me.Controls.Add(LB)
LB.Bounds = RichTextBox1.Bounds
RichTextBox1.Hide()
End Sub
Later, when you move the ListBox back, retrieve the size stored in the Tag:
If Not IsNothing(LB.Tab)
LB.Size = LB.Tag
End If
Output:
Form2.Listbox1.Parent = Form1
Form1.RichTextBox1.Visible = false
Form2.Listbox1.dock = DockStyle.Fill
The cool thing here is any code written in Form2 for Listbox1 will still function while it's sitting in Form1.
P.S. Rename your controls.

How to create any one dynamic controls with a for loop without using location property and the form should grow automatically

How to create multiple button controls with a for loop without getting the controls overlapped and without using location property in Vb.Net.
I have created 'n' number of vb controls dynamically but the created controls are getting overlapped to each other. When I use location property to each controls all the controls are getting displayed as per the location value.
The real problem is, I'm using a panel of width 300 and height 300, under that I need to display the dynamically created controls. I have figured it out which is tedious work and does take a lot of time. My idea is to find the panel width and height then need to check whether the new control which is getting created has ample of space to fit inside the panel.
I need to know few things,
1) How to display the controls dynamically using for loop without getting overlapped over each other and without using location property.
2) I need the container or the panel to grow as per the number of controls which gets created dynamically.
3) Accessing each controls which got displayed using an ID or educate or explain me any better idea.
I created a new WinForms project and added a Button to the top of the form. I added a FlowLayoutPanel under that and made it narrow enough to fit a single Button widthwise. I set the AutoSize property of the FLP to True and the FlowDirection to TopDown. I then added this code:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'Create the new Button.
Dim btn As New Button
'Add it to the FLP
FlowLayoutPanel1.Controls.Add(btn)
'Get the position of the bottom, left of the Button relative to the form.
Dim pt = PointToClient(btn.PointToScreen(New Point(0, btn.Height)))
'Resize the form to provide clearance below the new Button.
ClientSize = New Size(ClientSize.Width, pt.Y + 10)
End Sub
I then ran the project and started clicking the Button I added. As expected, each click added a new Button to the FLP in a vertical column and the form resized to fit. In order to access such controls in code, you can simply index the Controls collection of the FLP.
try this helps you.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
'Do Something
Else
'Do Something else
End If
Panel1.Controls.Clear()
For i As Integer = 0 To 10 Step 1
Dim b15 As New Button
b15.Text = "Test3"
b15.ID = "a" & i
AddHandler b15.Click, AddressOf updateFunc
Panel1.Controls.Add(b15)
Next
End Sub

Change the tooltip text when selecting item in listview

I have a listview containing the source addresses of files (from user system) and the destination addresses (two columns, multilpe selection = false).
Since the source addresses might be quite long like:
d:\root\branch1\branch2\branch3\branch4\myfile.dat
the first column shows just:
d:\ ... \myfile.dat
The real path is stored in the ListViewItem.Tag
I want to have a tooltip showing the whole path every time the user clicks (or changes) the selected item. I came out with this:
Private Sub ListView1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ListView1.SelectedIndexChanged
For Each locItem As ListViewItem In ListView1.SelectedItems
With ToolTip1
.RemoveAll()
.SetToolTip(ListView1, locItem.Tag)
End With
Next
End Sub
Now, the tooltip does change, but it always skip one selection. That is:
selecting item 1: tooltip shows correctly
selecting item 2: tooltip don't show
selecting item 3: tooltip shows correctly
selecting item 5: tooltip don't show
selecting item 2: tooltip shows correctly (selection went back to item 2 which didn't show the 1st time)
Any idea?
PS: I am using Visual Studio Community 2015
PPS: I also need to have the View property set to View.Details (to show both columns and headers), so setting ShowItemToolTip = True does not work
CURRENT SOLUTION
I found a workaround, destroying and recreating the tooltip control. Now the tooltip shows correctly on every item:
Private myTooltip As ToolTip
Private Sub ListView1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ListView1.SelectedIndexChanged
If myTooltip IsNot Nothing Then myTooltip.Dispose()
myTooltip = New ToolTip
For Each locItem As ListViewItem In ListView1.SelectedItems
myTooltip.SetToolTip(ListView1, locItem.Tag)
Next
End Sub
I'm still baffled about the skipping in the first approach.
ListView has a property called ShowItemToolTips (https://msdn.microsoft.com/en-us/library/system.windows.forms.listview.showitemtooltips(v=vs.110).aspx). You can set that to true and then set the ToolTipText property of the ListViewItems to the long path.
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
ListView1.ShowItemToolTips = True
Dim lvi1 As New ListViewItem With {.Text = "d:\..\myFile.dat", .Tag = "d:\myLongPath\myFile.dat", .ToolTipText = .Tag}
Dim lvi2 As New ListViewItem With {.Text = "d:\..\myFile2.dat", .Tag = "d:\myLongPath\myFile2.dat", .ToolTipText = .Tag}
ListView1.Items.Add(lvi1)
ListView1.Items.Add(lvi2)
End Sub

Set Length of ComboBox

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

Datagridview won't change checkbox of first row (vb.net)

I have a datagridview (here called cameraTable). One column of the datagridview is purely checkboxes. I have a button that when clicked will check all the boxes in the column, aka select all. Here's the code:
Private Sub btnSelectAll_Click(sender As Object, e As EventArgs) Handles btnSelectAll.Click
For Each row As DataGridViewRow In cameraTable.Rows
DirectCast(row.Cells("CheckBox"), DataGridViewCheckBoxCell).Value = _
True
Next
End Sub
The problem I'm having is that the initial box (i.e. row zero) never changes to checked. I tried these:
DirectCast(cameraTable(0, 0), DataGridViewCheckBoxCell).Value = True ' doesn't work
cameraTable.Rows(0).Cells(0).Value = True ' doesn't work
Neither change the box to checked, but the other rows within the column change without a problem. I even did a msgbox that prints out the value, and turns out to be "True". So the value of the checkbox has changed, but the check box in the datagridview is still unchecked. Any ideas?
Thanks for all the help!
-K
The datagrid will not get INotifyPropertyChanged events (or will not process them) for the row/cell that is currently selected. If you have other columns that can be edited, move the focused column to it.
If all else fails, reload the grid after seting the values by setting the datasource = nothing and then back to what it was.
Steve is right. What I did was when the check box is clicked, I set the focus to another cell on that row (my dgv is set to FullRowSelect):
Private Sub dgv_CellContentClick(sender As System.Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgv.CellContentClick
If e.ColumnIndex = iCBColIDX Then
dgv.CurrentCell = dgv.Rows(e.RowIndex).Cells("sts")
End If
End Sub
Make your checkbox column width=20 instead of 18.
No, I don't know why, but it helps.
Thanks this man.
PS. It isn't a joke, it's a bug.