I have a databound ListItems combobox with AutoComplete.SuggestAppend
and would like to navigate out of the combobox to different controls using the up/down arrow keys rather than scrolling the items.
The issue is that if the text isn't completed the suggested text remains highlighted while the next control has focus.
Link to image example
Here is some code showing a simple example of what I am doing
Public Class Form1
Dim PreventCboBoxChanging As Boolean
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ComboBox1.DataSource = New List(Of String)(New String() {10, 11, 20, 30})
ComboBox1.AutoCompleteSource = AutoCompleteSource.ListItems
ComboBox1.AutoCompleteMode = AutoCompleteMode.SuggestAppend
End Sub
Private Sub ComboBox1_KeyDown(sender As Object, e As KeyEventArgs) Handles ComboBox1.KeyDown
If PreventCboBoxChanging = True Then
e.Handled = True
End If
PreventCboBoxChanging = False
End Sub
Private Sub ComboBox1_PreviewKeyDown(sender As Object, e As PreviewKeyDownEventArgs) Handles ComboBox1.PreviewKeyDown
If e.KeyCode = Keys.Down Or e.KeyCode = Keys.Up Then
PreventCboBoxChanging = True
TextBox1.Select()
End If
End Sub
Private Sub TextBox1_KeyDown(sender As Object, e As KeyEventArgs) Handles TextBox1.KeyDown
If e.KeyCode = Keys.Down Or e.KeyCode = Keys.Up Then
ComboBox1.Select()
End If
End Sub
Private Sub ComboBox1_Validating(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles ComboBox1.Validating
Dim index As Integer = sender.FindString(sender.Text)
If index > -1 Then
sender.SelectedIndex = index
Else
e.Cancel = True
Me.Text = ""
Beep()
End If
End Sub
End Class
Is there any way to deselect the text?
I found the solution in another thread. Needed to turn off the Combobox AutoComplete Mode, change focus then reenable SuggestAppend mode under the PreviewKeyDown event.
Private Sub ComboBox1_PreviewKeyDown(sender As Object, e As PreviewKeyDownEventArgs) Handles ComboBox1.PreviewKeyDown
If e.KeyCode = Keys.Down Or e.KeyCode = Keys.Up Then
ComboBox1.AutoCompleteMode = AutoCompleteMode.None
TextBox1.Select()
ComboBox1.AutoCompleteMode = AutoCompleteMode.SuggestAppend
End If
End Sub
This should make it:
Private Sub ComboBox1_Leave(sender As Object, e As EventArgs) Handles ComboBox1.Leave
ComboBox1.SelectionLength = 0
End Sub
Related
I have a combobox in my Userform. Whilst this is in focus, I am wanting to use the keyboard for WASD controls. However, I find that when I press WASD the Combobox is bringing up values beginning with these letters. Also, the arrow keys are cycling through the options as well.
Is there anyway to restrict these commands?
I have tried
Tool.AutoCompleteMode = AutoCompleteMode.None
This does not stop is doing this. Does anybody have any clue how I could access more specific controls to stop this kind of autofill happening?
If you have only the Combobox control in your form and no other input controls, such as textbox, you can try the following code:
Please set e.Handled = True in the KeyPress event of the Combobox.
Private Sub ComboBox1_KeyPress(sender As Object, e As KeyPressEventArgs) Handles ComboBox1.KeyPress
e.Handled = True
End Sub
If you have some input controls, you want to retain the editing function, and you want to not interfere with the KeyPress event of the form.
You could refer to the following steps.
(1) Please set Me.KeyPreview = False in the KeyDown event of each input control.
(2) Please set e.Handled = True in the KeyPress event of ComboBox1.
(3) When double-clicking the form to enter WASD, you can set ComboBox1.Focus().
Sample code:
Public Class Form1
Private Sub Form1_KeyPress(sender As Object, e As KeyPressEventArgs) Handles MyBase.KeyPress
'edit your code
Dim offset As Integer = 10
If e.KeyChar = "a" Then
PictureBox1.Location = New Point(PictureBox1.Location.X - offset, PictureBox1.Location.Y)
ElseIf e.KeyChar = "w" Then
PictureBox1.Location = New Point(PictureBox1.Location.X, PictureBox1.Location.Y - offset)
ElseIf e.KeyChar = "s" Then
PictureBox1.Location = New Point(PictureBox1.Location.X, PictureBox1.Location.Y + offset)
ElseIf e.KeyChar = "d" Then
PictureBox1.Location = New Point(PictureBox1.Location.X + offset, PictureBox1.Location.Y)
End If
e.Handled = True
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.KeyPreview = True
End Sub
Private Sub Form1_DoubleClick(sender As Object, e As EventArgs) Handles MyBase.DoubleClick
ComboBox1.Focus()
Me.KeyPreview = True
End Sub
Private Sub ComboBox1_KeyPress(sender As Object, e As KeyPressEventArgs) Handles ComboBox1.KeyPress
e.Handled = True
End Sub
Private Sub TextBox1_KeyDown(sender As Object, e As KeyEventArgs) Handles TextBox1.KeyDown
Me.KeyPreview = False
End Sub
End Class
Result:
The code says everything, if I press F1 and I'm already with Button1 selected, then it should select Button2 and vice-versa.
If keyData = Keys.F1 Then
If Button1.Select() = True Then
Button2.Select()
ElseIf Button2.Select() = True Then
Button1.Select()
Else
Button1.Select()
End If
End If
But the expression "Button2.Select() = True" doesn't return a value.
Private Sub Form1_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
If e.KeyValue = Keys.F1 Then
If ActiveControl.Name = "Button1" Then
Button2.Select()
Else
Button1.Select()
End If
End If
End Sub
Actually, F1 is a poor choice because it is traditionally the "Help" key.
We can use form keydown (set form keypreview property to true) or use button previewkeydown like these:
Private Sub Button1_PreviewKeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.PreviewKeyDownEventArgs) Handles Button1.PreviewKeyDown
If e.KeyCode = Keys.F1 Then
Button2.Focus()
End If
End Sub
Private Sub Button2_PreviewKeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.PreviewKeyDownEventArgs) Handles Button2.PreviewKeyDown
If e.KeyCode = Keys.F1 Then
Button1.Focus()
End If
End Sub
I have set Datagridview .ReadOnly property to True, and then added a button column. Button column is meant for edit button when clicked, but I wish to edin only currently selected row. This is what I tried:
EDIT:
Public Class Form2
Private Sub Form2_Resize(sender As Object, e As EventArgs) Handles Me.Resize
Me.DataGridView1.Height = 0.8 * Me.Height
End Sub
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'TODO: This line of code loads data into the 'Users._USERS' table. You can move, or remove it, as needed.
Me.USERSTableAdapter.Fill(Me.Users._USERS)
Me.DataGridView1.DefaultCellStyle.Font = New Font("Arial", 7)
End Sub
Protected Overrides Sub OnLoad(e As EventArgs)
MyBase.OnLoad(e)
For i As Integer = 0 To DataGridView1.Rows.Count - 1
DataGridView1.Rows(i).ReadOnly = True
Next
End Sub
Private Sub DataGridView1_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellContentClick
Dim yourColumnIndex As Int32 = 3
If e.ColumnIndex = yourColumnIndex Then
If MsgBox("Do you wish to edit records?", vbQuestion + vbYesNo, "Edit records") = vbYes Then
DataGridView1.Rows(e.RowIndex).ReadOnly = False
End If
End If
End Sub
Private Sub DataGridView1_RowLeave(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.RowLeave
DataGridView1.Rows(e.RowIndex).ReadOnly = True
End Sub
End Class
You can't set the grid's ReadOnly property to true. After the rows are added to the grid, you would have to loop through your rows and set the ReadOnly property for each row:
Protected Overrides Sub OnLoad(e As EventArgs)
MyBase.OnLoad(e)
For i As Integer = 0 To DataGridView1.Rows.Count - 1
DataGridView1.Rows(i).ReadOnly = True
Next
End Sub
Note: you can't set these properties in the form's constructor, a quirk of the DataGridView control.
Then use the RowIndex property provided by the e parameter:
Private Sub DataGridView1_CellContentClick(sender As Object,
e As DataGridViewCellEventArgs)
Handles DataGridView1.CellContentClick
If e.ColumnIndex = 3 Then
DataGridView1.Rows(e.RowIndex).ReadOnly = False
End If
End Sub
Set it back to true when leaving the row:
Private Sub DataGridView1_RowLeave(sender As Object,
e As DataGridViewCellEventArgs)
Handles DataGridView1.RowLeave
DataGridView1.Rows(e.RowIndex).ReadOnly = True
End Sub
This is working, I just changed your suggestion a little bit (DatagridView Readonly property must be set to False):
Protected Overrides Sub OnLoad(e As EventArgs)
MyBase.OnLoad(e)
For Each band As DataGridViewBand In DataGridView1.Columns
band.ReadOnly = True
Next
End Sub
Private Sub DataGridView1_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellContentClick
Dim yourColumnIndex As Int32 = 3
If e.ColumnIndex = yourColumnIndex Then
If MsgBox("Do you wish to edit record?", vbQuestion + vbYesNo, "Edit record") = vbYes Then
For Each band As DataGridViewBand In DataGridView1.Columns
band.ReadOnly = False
Next
End If
End If
End Sub
Private Sub DataGridView1_RowLeave(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.RowLeave
For Each band As DataGridViewBand In DataGridView1.Columns
band.ReadOnly = True
Next
End Sub
Thanks for all your help Lars!
How to prevent form being closed by alt+f4 keys in keydown event? problem i am facing is keeping ALT key pressed and pressing F4 closes form but i want to prevent form from closing. Below is my code
Private Sub frminstituteselect_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
If e.Alt = True And e.KeyCode = Keys.F4 Then
e.Handled = True
End If
End Sub
Try like this
Private ALT_F4 As Boolean = False
Private Sub frminstituteselect_FormClosing(sender As Object, e As System.Windows.Forms.FormClosingEventArgs) Handles Form1.FormClosing
If ALT_F4 Then
e.Cancel = True
Return
End If
End Sub
Private Sub frminstituteselect_KeyDown(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles Form1.KeyDown
ALT_F4 = (e.KeyCode.Equals(Keys.F4) AndAlso e.Alt = True)
End Sub
or simply
Private Sub frminstituteselect_FormClosing(sender As Object, e As System.Windows.Forms.FormClosingEventArgs) Handles Form1.FormClosing
e.Cancel = True
End Sub
I'm trying to simulate a headerclick in datagridview column 1 with shortcut keys but I dont know how.
Private Sub frm_lista_KeyDown(ByVal sender As Object, ByVal e As KeyEventArgs) Handles Me.KeyDown
If e.KeyCode = Keys.S And e.Alt Then
'this handler exists
DataGridView1_ColumnHeaderMouseClick(whathere, whathere)
End If
End Sub
Any help?
Make sure the form has this property set:
Me.KeyPreview = True
Since you are trying to specify column 1 from a keyboard event, you can pass your own event arguments:
Private Sub Form1_KeyDown(sender As Object, e As KeyEventArgs) Handles MyBase.KeyDown
If ((Control.ModifierKeys And e.Alt) AndAlso e.KeyCode = Keys.S) Then
Dim mea As New MouseEventArgs(MouseButtons.None, -1, -1, -1, -1)
Dim dgvcme As New DataGridViewCellMouseEventArgs(1, -1, -1, -1, mea)
DataGridView1_ColumnHeaderMouseClick(DataGridView1, dgvcme)
End If
End Sub
The event should now have the e.ColumnIndex property set.
Private Sub DataGridView1_ColumnHeaderMouseClick(sender As Object, e As DataGridViewCellMouseEventArgs) Handles DataGridView1.ColumnHeaderMouseClick
If e.ColumnIndex = 1 Then
MessageBox.Show("OK")
End If
End Sub
Alternatively, you could just call a sub-routine from both places:
Private Sub Form1_KeyDown(sender As Object, e As KeyEventArgs) Handles MyBase.KeyDown
If ((Control.ModifierKeys And e.Alt) AndAlso e.KeyCode = Keys.S) Then
Call HandelColumnOneClick()
End If
End Sub
Private Sub DataGridView1_ColumnHeaderMouseClick(sender As Object, e As DataGridViewCellMouseEventArgs) Handles DataGridView1.ColumnHeaderMouseClick
If e.ColumnIndex = 1 Then
Call HandleColumnOneClick()
End If
End Sub
Private Sub HandleColumnOneClick()
'// Do Something
End Sub