DataGridView editable combobox Left Right Arrow keys

Q

QSIDeveloper

When I have an editable combobox in a DataGridView and the user tries to
correct an error they can not move the cursor from character to character
with the arrow keys. The arrow keys move focus to the next cell. How can I
change this behavior when editing the value in a combo box in a DataGridView
control?
 
L

Linda Liu[MSFT]

Hi John,
When I have an editable combobox in a DataGridView and the user tries to
correct an error they can not move the cursor from character to character
with the arrow keys.

Firstly, it seems that you are not using the standard
DataGridViewComboBoxColumn in the DataGridView, because the cells under the
DataGridViewComboBoxColumn are not editable.

Secondly, when the user tries to move the input cursor within the cell with
the arrow keys, is the cell in edit mode? If the cell is in edit mode, the
user should be able to move the input cursor within the cell with the arrow
keys.

To solve the problem more quickly, could you please send me a sample
project that could just reproduce the problem? To get my actual email
address, remove 'online' from my displayed email address.

Thank you for your cooperation and I look forward to your reply.

Sincerely,
Linda Liu
Microsoft Online Community Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
L

Linda Liu[MSFT]

Hi John,

Thank you for your sample project! I did see the problem when I run it on
my machine.

If a DataGridViewTextBoxCell is in edit mode and we press the Left or Right
arrow key, the input cursor will be moved within this cell. However, the
Left or Right arrow key doesn't work the same in a DataGridViewComboBoxCell
when it is in edit mode. Because by default a DataGridViewComboBoxCell is
not editable at all, the DataGridView class treats textbox cells and
combobox cells differently. I'd like to say that this behavior is by design.

A workaround is derive a new class from the DataGridView class and override
the ProcessDataGridViewKey method. In the override method, we get the
current edit control and set the SelectionStart property of the control to
the value we want and then return true to indicate that we have processed
this key.

The following is a sample:

class MyDataGridView : DataGridView
{
protected override bool ProcessDataGridViewKey(KeyEventArgs e)
{
if (e.KeyData == Keys.Left || e.KeyData == Keys.Right)
{
if (this.EditingControl != null)
{
if (this.EditingControl.GetType() ==
typeof(DataGridViewComboBoxEditingControl))
{
ComboBox control = this.EditingControl as ComboBox;
if (control.DropDownStyle !=
ComboBoxStyle.DropDownList)
{
switch (e.KeyData)
{
case Keys.Left:
if (control.SelectionStart > 0)
{
control.SelectionStart--;
return true;
}
break;
case Keys.Right:
if (control.SelectionStart <
control.Text.Length)
{
control.SelectionStart++;
return true;
}
break;
}
}
}
}

}

return base.ProcessDataGridViewKey(e);
}
}

The derived DataGridView works well on my side. Please try it on your form
to see if there is any problem and let me know the result.

Sincerely,
Linda Liu
Microsoft Online Community Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
F

Fred

Dans : Linda Liu[MSFT] disait :
Hi John,

Thank you for your sample project! I did see the problem when I run
it on my machine.

If a DataGridViewTextBoxCell is in edit mode and we press the Left or
Right arrow key, the input cursor will be moved within this cell.
However, the Left or Right arrow key doesn't work the same in a
DataGridViewComboBoxCell when it is in edit mode. Because by default
a DataGridViewComboBoxCell is not editable at all, the DataGridView
class treats textbox cells and combobox cells differently. I'd like
to say that this behavior is by design.

A workaround is derive a new class from the DataGridView class and
override the ProcessDataGridViewKey method. In the override method,
we get the current edit control and set the SelectionStart property
of the control to the value we want and then return true to indicate
that we have processed this key.


Hello,

I didn't see John's project, but in a quite similar case, I created a
class that inherits a combo and implements IDataGridViewEditingControl.
It is then easy to program the EditingControlWantsInputKey method.
 
Q

QSIDeveloper

Thank you Linda for your prompt reply. That solved my problem.

Fred, I tried the EditingControlWantsInputKey method but could not get it to
work. Could you post the code here so I can compare it ?


Fred said:
Dans : Linda Liu[MSFT] disait :
Hi John,

Thank you for your sample project! I did see the problem when I run
it on my machine.

If a DataGridViewTextBoxCell is in edit mode and we press the Left or
Right arrow key, the input cursor will be moved within this cell.
However, the Left or Right arrow key doesn't work the same in a
DataGridViewComboBoxCell when it is in edit mode. Because by default
a DataGridViewComboBoxCell is not editable at all, the DataGridView
class treats textbox cells and combobox cells differently. I'd like
to say that this behavior is by design.

A workaround is derive a new class from the DataGridView class and
override the ProcessDataGridViewKey method. In the override method,
we get the current edit control and set the SelectionStart property
of the control to the value we want and then return true to indicate
that we have processed this key.


Hello,

I didn't see John's project, but in a quite similar case, I created a
class that inherits a combo and implements IDataGridViewEditingControl.
It is then easy to program the EditingControlWantsInputKey method.
 
F

Fred

Dans : QSIDeveloper disait :
Fred, I tried the EditingControlWantsInputKey method but could not
get it to work. Could you post the code here so I can compare it ?

Yes, this is a very simple code that only allows string value type.
Actually my real exemple doesn't inherit a ComboBox but a UserControl so I had to cut a lot of code but this one works quite fine even if not so complete

To use this new column type you can write :
Dim cc As New DataGridViewComboColumn
cc.HeaderText = "Test"
cc.ValueType = GetType(String)
Me.DataGridView1.Columns.Add(cc)

So, the most important part now (care about the line breaks)

Imports System
Imports System.ComponentModel
Imports System.Windows.Forms

Public Class DataGridViewComboColumn
Inherits DataGridViewColumn

Sub New()
MyBase.New(New DataGridViewComboCell())
End Sub

Public Overrides Property CellTemplate() As DataGridViewCell
Get
Return MyBase.CellTemplate
End Get
Set(ByVal value As DataGridViewCell)
If Not (value Is Nothing) AndAlso Not value.GetType().IsAssignableFrom(GetType(DataGridViewComboCell)) Then
Throw New InvalidCastException("DataGridViewComboCell expected")
End If
MyBase.CellTemplate = value
End Set
End Property

Public Overrides Property [ReadOnly]() As Boolean
Get
Return False
End Get
Set(ByVal value As Boolean)
'MyBase.[ReadOnly] = value
End Set
End Property

End Class


Public Class DataGridViewComboCell
Inherits DataGridViewComboBoxCell

Public Overrides ReadOnly Property EditType() As Type
Get
Return GetType(DataGridViewComboEditingControl)
End Get
End Property

Public Overrides ReadOnly Property FormattedValueType() As System.Type
Get
Return GetType(String)
End Get
End Property

Public Overrides ReadOnly Property ValueType() As System.Type
Get
Return GetType(String)
End Get
End Property

Public Overrides Function KeyEntersEditMode(ByVal e As System.Windows.Forms.KeyEventArgs) As Boolean
If e.Alt And e.KeyCode = Keys.Down Then Return True
Return MyBase.KeyEntersEditMode(e)
End Function

Protected Overrides Function GetFormattedValue(ByVal value As Object, ByVal rowIndex As Integer, ByRef cellStyle As System.Windows.Forms.DataGridViewCellStyle, ByVal valueTypeConverter As System.ComponentModel.TypeConverter, ByVal formattedValueTypeConverter As System.ComponentModel.TypeConverter, ByVal context As System.Windows.Forms.DataGridViewDataErrorContexts) As Object
If value IsNot Nothing Then Return value Else Return cellStyle.NullValue
End Function

Public Overrides Function ParseFormattedValue(ByVal formattedValue As Object, ByVal cellStyle As System.Windows.Forms.DataGridViewCellStyle, ByVal formattedValueTypeConverter As System.ComponentModel.TypeConverter, ByVal valueTypeConverter As System.ComponentModel.TypeConverter) As Object
Return DirectCast(formattedValue, String)
End Function

Public Overrides Sub InitializeEditingControl(ByVal rowIndex As Integer, ByVal initialFormattedValue As Object, ByVal dataGridViewCellStyle As System.Windows.Forms.DataGridViewCellStyle)
MyBase.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle)
Dim editingControl As DataGridViewComboEditingControl = TryCast(MyBase.DataGridView.EditingControl, DataGridViewComboEditingControl)
If (Not editingControl Is Nothing) Then
editingControl.DropDownStyle = ComboBoxStyle.DropDown
editingControl.Text = initialFormattedValue
End If
End Sub

End Class


Public Class DataGridViewComboEditingControl
Inherits ComboBox
Implements IDataGridViewEditingControl

Private _dataGridView As DataGridView
Private _rowIndex As Int32
Private _valueChanged As Boolean

Public Sub ApplyCellStyleToEditingControl(ByVal dataGridViewCellStyle As System.Windows.Forms.DataGridViewCellStyle) Implements System.Windows.Forms.IDataGridViewEditingControl.ApplyCellStyleToEditingControl
Me.Font = dataGridViewCellStyle.Font
Me.ForeColor = dataGridViewCellStyle.ForeColor
Me.BackColor = dataGridViewCellStyle.BackColor
End Sub

Public Property EditingControlDataGridView() As System.Windows.Forms.DataGridView Implements System.Windows.Forms.IDataGridViewEditingControl.EditingControlDataGridView
Get
Return Me._dataGridView
End Get
Set(ByVal value As System.Windows.Forms.DataGridView)
Me._dataGridView = value
End Set
End Property

Public Property EditingControlFormattedValue() As Object Implements System.Windows.Forms.IDataGridViewEditingControl.EditingControlFormattedValue
Get
Return Me.Text
End Get
Set(ByVal value As Object)
Me.Text = value
End Set
End Property

Public Property EditingControlRowIndex() As Integer Implements System.Windows.Forms.IDataGridViewEditingControl.EditingControlRowIndex
Get
Return Me._rowIndex
End Get
Set(ByVal value As Integer)
Me._rowIndex = value
End Set
End Property

Public Property EditingControlValueChanged() As Boolean Implements System.Windows.Forms.IDataGridViewEditingControl.EditingControlValueChanged
Get
Return Me._valueChanged
End Get
Set(ByVal value As Boolean)
Me._valueChanged = value
End Set
End Property

Public Function EditingControlWantsInputKey(ByVal keyData As System.Windows.Forms.Keys, ByVal dataGridViewWantsInputKey As Boolean) As Boolean Implements System.Windows.Forms.IDataGridViewEditingControl.EditingControlWantsInputKey
If keyData = Keys.F5 Then Return True
If keyData = (Keys.Alt And Keys.Down) And Me.Enabled Then Return True
If keyData = Keys.Down And Not Me.DroppedDown Then Return False
If keyData = Keys.Up And Not Me.DroppedDown Then Return False
If keyData = Keys.Enter And Me.DroppedDown Then Return True
If keyData = Keys.Right And Not Me.DroppedDown Then Return True
If keyData = Keys.Left And Not Me.DroppedDown Then Return True
If keyData = Keys.End And Not Me.DroppedDown Then Return True
If keyData = Keys.Home And Not Me.DroppedDown Then Return True
If keyData = Keys.Escape And Me.DroppedDown Then Return True
If keyData = Keys.Down And Me.DroppedDown Then Return True
If keyData = Keys.Up And Me.DroppedDown Then Return True
Return dataGridViewWantsInputKey
End Function

Public ReadOnly Property EditingPanelCursor() As System.Windows.Forms.Cursor Implements System.Windows.Forms.IDataGridViewEditingControl.EditingPanelCursor
Get
Return MyBase.Cursor
End Get
End Property

Public Function GetEditingControlFormattedValue(ByVal context As System.Windows.Forms.DataGridViewDataErrorContexts) As Object Implements System.Windows.Forms.IDataGridViewEditingControl.GetEditingControlFormattedValue
Return Me.Text
End Function

Public Sub PrepareEditingControlForEdit(ByVal selectAll As Boolean) Implements System.Windows.Forms.IDataGridViewEditingControl.PrepareEditingControlForEdit
End Sub

Public ReadOnly Property RepositionEditingControlOnValueChange() As Boolean Implements System.Windows.Forms.IDataGridViewEditingControl.RepositionEditingControlOnValueChange
Get
Return False
End Get
End Property

Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)
MyBase.OnTextChanged(e)
Me.EditingControlValueChanged = True
Me.EditingControlDataGridView.NotifyCurrentCellDirty(True)
End Sub

Protected Overrides Sub OnSelectedIndexChanged(ByVal e As System.EventArgs)
MyBase.OnSelectedIndexChanged(e)
Me.EditingControlValueChanged = True
Me.EditingControlDataGridView.NotifyCurrentCellDirty(True)
End Sub

End Class
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top