Listbox jump item during input - vb.net

Probably it's very easy, but I have searched for a post or somehone who have the same problem without fortune. I have a Listbox in Vb Net, which contains a list of names.
in vb6, while typing in the listbox the selected item changed automatically based on the letters typed until completion, but I can't find a method that repeats the same thing in VS, as the only thing it lets me do is identify only the first one letter typed in the listbox. So, if in the list there are two similar names like Autocarro or Automobile, if after the 'A' I type the 'U' the cursor moves to the 'U' of 'Urban'.
Could anyone help me find a solution whithout using a textbox?
Thanks in advance

You can use a ComboBox with the DropDownStyle set to Simple. This displays a TextBox combined with a ListBox (hence the name Combo Box).
To make it select entries automatically you can add a TextChanged event handler with the following code:
private void ComboBox1_TextChanged(object sender, EventArgs e)
{
int inputLength = comboBox1.Text.Length;
if (inputLength > 0) {
int index = comboBox1.FindString(comboBox1.Text);
if (index >= 0) {
comboBox1.SelectedIndex = index;
comboBox1.Focus();
comboBox1.SelectionStart = inputLength;
comboBox1.SelectionLength =
((string)comboBox1.Items[index]).Length - inputLength;
}
}
}
Note, however, that editing the text box part becomes a bit difficult as the selection mechanism kicks in every time you edit the text. E.g. deleting text with Dellete or Backspace does not work well, as the automatic selection restores the text immediately. You can delete the whole text by typing Ctrl-A, Delete.
ComboBox after having typed "cl":

Try this (Works both for text box and combobox, not sure if it works directly in list box, you can try in this lime), what you can do is add textbox on top of list box and run second code to add data to textbox as suggestion
ComboBox1.AutoCompleteMode = AutoCompleteMode.SuggestAppend
Or this one
Dim iddata As New AutoCompleteStringCollection()
Dim idtable As New DataTable
idtable = (your datatable source)
For Each r As DataRow In idtable.Rows
iddata.Add(r("id").ToString)
Next
With Textbox1
.AutoCompleteCustomSource = iddata
.AutoCompleteMode = AutoCompleteMode.Suggest
.AutoCompleteSource = AutoCompleteSource.CustomSource
End With

Related

How can I read the SelectedItem of a Listbox?

I am trying to get the selected text in a ListBox to show in a list box.
I have a button that when I click, will show the text of a Selected item in a ListBox.
I've already tried getting the list box to show the text in a textbox using Listbox.SelectedItem:
Listbox1.SelectedItem = Textbox1.Text
When I do this, I get the error:
System.NullReferenceException: 'Object variable or With block variable
not set.'
Your description is somewhat upside-down.
It's not clear whether you want to set a ListBox.SelectedItem using the Text of a TextBox or you want to set a TextBox.Text with the text of the SelectedItem of a ListBox.
The code says one thing, the description another. The error you have is probably caused by a null SelectedItem (you haven't selected anything).
But, if you want to set a TextBox.Text with the ListBox.SelectedItem text, you can use the GetItemText() method. This method has a plus, it won't raise an exception if the Listbox has no selected Items (the SelectedItem is null (nothing)).
TextBox1.Text = ListBox1.GetItemText(ListBox1.SelectedItem)
The opposite:
You can use the ListBox FindString() and FindStringExact() methods to locate an item in the control's collection corresponding to a given string.
The former finds the first items in the ListBox that starts with the specified string, the latter matches only the whole string.
The search can begin from a specific index. It's not case sensitive.
listBox1.SelectedIndex = listBox1.FindString(textBox1.Text, 0)
' or
listBox1.SelectedIndex = listBox1.FindStringExact(textBox1.Text, 0)
You can continue the search specifying, as the starting point, the index of the item previously found:
private int lboxSearchIndex = -1;
Private Sub ButtonSearch_Click(sender As Object, e As EventArgs) Handles ButtonSearch.Click
lboxSearchIndex = listBox1.FindString(textBox1.Text, lboxSearchIndex)
listBox1.SelectedIndex = lboxSearchIndex
End Sub
Setting the SelectedItem is like using the FindStringExact() method.
Only a full match will set the item, but it's case sensitive.
Listbox1.Text=textbox1.text
Let me know its help you

Select Textbox using For Loop

Sorry this is weird and silly question but I need a solution of this...
I have 30 textboxes named as Txt1,Txt2,Txt3,...,Txt30
I have to fill textbox as Txt1.text = 0 on button click..
Is there any way like On Button Click
Dim i as Integer
For i = 1 to 30 '----- Possible in string but don't know if possible in textboxes
Txt(i).text = 0
Next
Or I have to write all 30 lines like
Txt1.text = 0
...
Txt30.text = 0
I don't know how this question asked, maybe Question improper.
Thanx in Advance...
If the textboxes are all contained in Controls collection of the Form, then it is really easy to loop over them
For Each(t in Me.Controls.OfType(Of TextBox)())
t.Text = "0"
Of course the advantage of this approach is that you don't have to worry if you add other textboxes to your form. They will be found using the foreach loop without having a fixed top limit.
And, if not all of your textboxes should be included in the loop, then you can simply use the Tag property of the textboxes that you want to use. For example, if you set the Tag property to the string "Y", then you can change the foreach loop to find only the controls with the matching Tag property
For Each t in Me.Controls.OfType(Of TextBox)() _
.Where(Function(x) x.Tag = "Y")
t.Text = "0"
The two solutions above works well if all your textboxes are contained in the same container (Form, GroupBox or Panel), instead, if these textboxes are dispersed in different containers (some in a groupbox, others in a panel etc) then you can build a List(Of TextBox) variable filling it with the textboxes instances and use it when the need arise
Dim myTexts = New List(Of TextBox)() From { Txt1, Txt2, Txt3, ....}
And loop over this variable
You can do as Steve said, but if you have other textboxes that you don't want to edit then there is another way:
For i = 1 to 30
dim found = Me.Controls.Find("Txt" & i, True) '<- the True argument is for recursive search
If Not IsNothing(found) AndAlso found.Length > 0 Then
found(0).Text = "0"
End If
Next
If your textboxes are all in the same control, for example GroupBox, you can do GroupBox.Controls.Find saving CPU resources

Accessing Textbox programmatically created

I need to read a datagrid numbers of items, and programmatically add tabs to one tabControl. No problem on reading the datagrid, no problem in creating the model in the tabcontrol. So, I read the number of items, create the tabs accordingly, with all textboxes already with the correct values and so on.
At this point, the user will update some information on the tabs created, and need to click a Update button. At this point, I need to read all tabs, one by one, accessing all textboxes created, and send this to my database.
The only thing I got no result till now is “How to access these programmatically created Textboxes?
This is how I create the textboxes inside the TabControl
Dim TXT As New TextBox
TXT = New TextBox
TXT.Location = New System.Drawing.Point(213, 25)
TXT.Width = 303
TXT.TextAlign = HorizontalAlignment.Center
TXT.Name = "TXT_02_" & tab_counter
TXT.Text = MAT_DTCP(1) 'ABERTURA
TXT.BackColor = ColorTranslator.FromOle(RGB(128, 255, 255))
FORM_01.TBC_DTCP.SelectedTab.Controls.Add(TXT)
You could use LINQ:
Dim allTextBoxes = From tab In FORM_01.TBC_DTCP.TabPages.Cast(Of TabPage)()
From txt In tab.Controls.OfType(Of TextBox)()
Where txt.Name.StartsWith("TXT_02_")
Select txt
For Each txt As TextBox In allTextBoxes
' ... '
Next

How to switch between DataGridViewTextBoxCell and DataGridViewComboBoxCell?

I want to have a DataGridView that has two columns. The first column will always be of type DataGridViewComboBoxColumn. Based on the selection in that column, I'd like to be able to change the corresponding cell in the second column to either a DataGridViewComboBoxCell or a DataGridViewTextBoxCell.
I'm thinking I just need to make the second column of type DataGridViewColumn, but don't understand the mechanics of how to change the cell type on the fly.
I'm working with VB.NET in Visual Studio 2005.
Thanks in advance!
Update: One way around it, I suppose, is to make the second column as a DataGridViewComboBoxColumn, and change the attributes of the cell so that it either behaves like a drop-down list, or as an (editable) drop-down with no elements. The latter looks enough like a text box that I could live with it, and it wouldn't involve changing the type of the cell.
I don't have the VB.Net version,but hopefully this quick C# snippet will help you or point you in the right direction.
In this example, I set up a simple DataGridView with 2 columns. The first being a DataGridViewComboBox populated with two choices: "Text" or "Combo".
The second column is initially set to DataGridViewTextBoxColumn from the designer.
I handle the CurrentCellDirtyStateChanged event on the DataGridView. I check if the cell is dirty and only check the first column (The ComboBox). You gotta call the CommitEdit to get the new value in the combo or else you will be looking at the previous value. Based on the selection in the combo box I then overwrite the cell in the 2nd column with a new cell of that type.
You would add your own logic (populate the drop downs and handle the value). You might want to store the value and then put it back into the cell or whatever.
Here is the code I used and did a quick and dirty test on:
private void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
if (dataGridView1.IsCurrentCellDirty == false)
{
return;
}
dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
if (dataGridView1.CurrentCell.ColumnIndex == 0)
{
if (((string)dataGridView1.CurrentCell.Value) == "Text")
{
dataGridView1.Rows[dataGridView1.CurrentCell.RowIndex].Cells[1] = new DataGridViewTextBoxCell();
}
else if (((string)dataGridView1.CurrentCell.Value) == "Combo")
{
dataGridView1.Rows[dataGridView1.CurrentCell.RowIndex].Cells[1] = new DataGridViewComboBoxCell();
}
}
}
Here is a quick VB translation, that I tested and works.
Public Class Form1
Private Sub DataGridView1_CurrentCellDirtyStateChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DataGridView1.CurrentCellDirtyStateChanged
If DataGridView1.IsCurrentCellDirty = False Then
Return
End If
DataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit)
If DataGridView1.CurrentCell.ColumnIndex = 0 Then
If CStr(DataGridView1.CurrentCell.Value) = "Text" Then
DataGridView1.Rows(DataGridView1.CurrentCell.RowIndex).Cells(1) = New DataGridViewTextBoxCell
ElseIf CStr(DataGridView1.CurrentCell.Value) = "Combo" Then
DataGridView1.Rows(DataGridView1.CurrentCell.RowIndex).Cells(1) = New DataGridViewComboBoxCell
End If
End If
End Sub
End Class
You will lose any value stored in that column, so you would need to save it first.
Jon
You can create your own cell template that hosts a user control. In the user control you add a textbox and a combobox, and add a method/property to show one and hide another.
This sample creates a radio button cell, it is not hard to change the code to host a user control.
dgvCell = new DataGridViewTextBoxCell(); // code to remove checkbox
dgvCell.Value = string.Empty;
dgv_modi_del_trans.Rows[1].Cells[0] = dgvCell;

How to set tooltips to combobox items # VB.NET?

I have a combobox with a given width.
It may occur that one row of the data is partially hidden (the combobox might be too narrow). I'd like to show the whole line by using a tooltip or right-click context menu.
Currently I can't find how to 'catch' the row that I'm currently holding on or passing over by mouse. Please tell me.
Thanks in advance!
Have you tried to increase the DropDownWidth property so that everything is visible?
Edit: To find the ideal width based on the items in the list:
var maxLength = 0;
// using the ComboBox to get a Graphics object:
using (var g = Graphics.FromHwnd(comboBox2.Handle)) {
foreach (var item in comboBox2.Items.Cast<string>()) {
var itemLength = g.MeasureString(item, comboBox2.Font);
maxLength = Math.Max((int) itemLength.Width, maxLength);
}
}
if (comboBox2.Items.Count > comboBox2.MaxDropDownItems) {
// correction when ScrollBar is displayed
maxLength += 15;
}
comboBox2.DropDownWidth = maxLength;
I put this code in the DropDown event of the ComboBox for testing. Maybe you can find a better place for it, like after populating the ComboBox...
Going in the same direction that Julien went, here is a generic extension method that will resize the drop down area regardless of how the combobox is filled (manually with strings or via data binding).
<Extension()> _
Public Sub AutosizeDropDownWidth(ByVal combobox As ComboBox)
Dim longestItem As Integer = 0
Using g = Graphics.FromHwnd(combobox.Handle)
Dim itemsAsText = (From item In combobox.Items _
Select combobox.GetItemText(item))
longestItem = CInt(itemsAsText.Max(Function(text) g.MeasureString(text, combobox.Font).Width))
End Using
' Account for scrollbar
If (combobox.Items.Count > combobox.MaxDropDownItems) Then longestItem += 15
' Resize as needed (but never smaller than the default width)
combobox.DropDownWidth = Math.Max(longestItem, combobox.Width)
End Sub
To use it then you can simply do the following...
Private Sub MyCombobox_DropDown(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyCombobox.DropDown
MyCombobox.AutosizeDropDownWidth()
End Sub
Note, I didn't test corner cases like an empty combobox in this code example.
Your're right, there really isn't a "Item.OnMouseOver", but I suppose you could (off the top of my head, so I've likely forgotten something)...
inherit from ComboBox,
override OnDrawItem (you may need to turn change .DrawMode to "Owner Drawn").
you will know which item is hovered in the OnDrawItem event/override from the EventArgs.
Set the tooltip on the control at that point.
optionally set a timer to manually show the tooltip if the above doesn't work automatically.