DataGrid ComboBox

D

Doug Bell

Hi I am still having problems with Tabbing through a DataGrid with a
DataGridComboBox Column.

I need to allow the User to Type the value into the ComboBox so consequently
its ComboBoxStyle is set to DropDown. This causes the Tabbing to work
incorrectly. Even though I am consuming the Windows Message WM_KEYUP, it
still Tabs through the ComboBox Column on to the next Column.

I found if I do not give the keyboard focus ie remark out
ColumnComboBox.Focus the Tabbing works correctly but the ComboBox doesn't.

I tried delaying the sending of the WM_SETFOCUS Message but that didn't work
either.

Can anyone think of a workaround for this or even another way to give the
user similar Functionality. They want to type the value in using the
keyboard but the values are fixed so I have been using the Validating Event
to ensure that they are values from the Combos list. And it helps them to
see the values as in the Combos DropDown.

Any thoughts appreciated.

Doug
 
C

ClayB

Try using PreProcessMessage to ignore the KEYUP instead of WndProc.

Public Overrides Function PreProcessMessage(ByRef msg As
System.Windows.Forms.Message) As Boolean
If msg.Msg = WM_KEYUP Then
Return True
End If
Return MyBase.PreProcessMessage(msg)
End Function

===================
Clay Burch
Syncfusion, Inc.
 
D

Doug Bell

Clay,
Again thanks for your input.

To use "PreProcessMessage" will I have to derive my DataGrid?

Doug
 
C

ClayB

No, it is in the combobox not the grid. in the derived combobox,
comment out the WndProc override and add the PreProcessMessage
override. Here is the code that worked for me in the sample posted in
the other thread.

Namespace DataGridTextBoxCombo
Public Class NoKeyUpCombo
Inherits ComboBox
Private WM_KEYUP As Integer = &H101

'Protected Overrides Sub WndProc(ByRef m As
System.Windows.Forms.Message)

' If m.Msg = WM_KEYUP Then
' 'ignore keyup to avoid problem with tabbing &
dropdownlist;
' Return
' End If
' MyBase.WndProc(m)
'End Sub 'WndProc


Public Overrides Function PreProcessMessage(ByRef msg As
System.Windows.Forms.Message) As Boolean
If msg.Msg = WM_KEYUP Then
Return True
End If
Return MyBase.PreProcessMessage(msg)
End Function
End Class 'NoKeyUpCombo
End Namespace

=====================
Clay Burch
Syncfusion, Inc.
 
D

Doug Bell

I get an Error
"'Function PreProcessMessage' can not be declared 'Overrides' because it
does not override a function in the base class"

Am I missing something?

Doug
 
D

Doug Bell

Clay,

You are a lifesaver.

I owe you a few beers if you get to Sydney.

Thanks,

Doug
 
G

Guest

Doug,

I had similar problem about half a year ago, and had it solved in a similar
way. I have extended the concept slightly - you may find it useful as well:

Private Sub moveIndex(ByVal count As Integer, ByVal moveDown As Boolean,
ByVal offset As Integer)
Dim origIndex As Integer = Me.SelectedIndex
Dim newIndex As Integer
If moveDown Then
Dim maxIndex As Integer = count - 1
If origIndex < maxIndex Then
newIndex = Math.Min(origIndex + offset, maxIndex)
Else
newIndex = origIndex
End If
ElseIf origIndex > 0 Then
newIndex = Math.Max(origIndex - offset, 0)
End If
If newIndex <> origIndex Then
Me.SelectedIndex = newIndex
If Not _startEditing Is Nothing Then
_startEditing(Me, System.EventArgs.Empty)
End If
End If
End Sub

Public Overrides Function PreProcessMessage(ByRef msg As
System.Windows.Forms.Message) As Boolean
Dim keyCode As Keys = CType((msg.WParam.ToInt32 And Keys.KeyCode), Keys)
Dim baseProcess As Boolean = True
If msg.Msg = _WM_KEYDOWN Then
Select Case keyCode
Case Keys.Up, Keys.Down, Keys.PageUp, Keys.PageDown
baseProcess = False
Dim count As Integer = Me.Items.Count
If count > 0 Then
Select Case keyCode
Case Keys.Up
moveIndex(count, False, 1)
Case Keys.Down
moveIndex(count, True, 1)
Case Else
Dim pageCount As Integer = Me.MaxDropDownItems
If keyCode = Keys.PageUp Then
moveIndex(count, False, pageCount)
ElseIf keyCode = Keys.PageDown Then
moveIndex(count, True, pageCount)
End If
End Select
End If
End Select
End If
Dim result As Boolean = True
If baseProcess Then
result = MyBase.PreProcessMessage(msg)
End If
Return result
End Function

Placing the above code inside the combo allows it to react to the navigation
button events

HTH
 
D

Doug Bell

Hi Thanks Sergey,
I took my project in yesterday for "Show and Tell" and the combo Navigation
was one of their next requests.
(I should have put a functional specification together)
I was going to try to try and work out a solution this morning so perfect
timing
..
Can you explain your "_startEditing" ?

The Code I have is pretty much based on Clay's example.

What is your _startEditing ?

Thanks

Doug
 
D

Doug Bell

Sergey, to clarify,
I have the navigation keys working with your extra code but I just wondered
what your
"startEditing" was doing?

Doug
 
G

Guest

Doug,

_startEditing is a private variable that I initialise in the
comboconstructor - it refers to AddressOf selectionChangeCommit procedure in
DataGridComboboxColumn class.

Here is the constructor for the DataGridComboboxColumn:

Public Sub New()
' Create our own customized Combobox, which is used in the DataGrid
_cbo = New gridComboBox(AddressOf selectionChangeCommit)
_cbo.DropDownStyle = ComboBoxStyle.DropDownList
' GridComboBox subscribes to the Leave Event. It occurs when the
' input focus leaves the ComboBox.
AddHandler _cbo.Leave, AddressOf leaveComboBox
' GridComboBox subscribes to the SelectionChangeCommitted Event.
' It occurs when the selected item has changed and that change
' is committed (save the changed data to the DataGrid TextBox).
AddHandler _cbo.SelectionChangeCommitted, AddressOf selectionChangeCommit
End Sub

Now the actual procedure:
' The ColumnStartedEditing method allows the DataGrid
' to show a pencil in the row header indicating the row
' is being edited. (base is the parent DataGridTextBoxColumn)
Private Sub selectionChangeCommit(ByVal sender As System.Object, ByVal e As
System.EventArgs)
_editing = True
MyBase.ColumnStartedEditing(CType(sender, Control))
End Sub
And leave procedure:
' Handle Combobox Behaviour when Focus leaves the Combobox.
Private Sub leaveComboBox(ByVal sender As System.Object, ByVal e As
System.EventArgs)
If _editing Then
' Set the Combobox ValueMember to the current RowColumn
' when the Focus leaves the Combobox.
SetColumnValueAtRow(_currencyManager, _rowNum, _cbo.Text)
_editing = False
' Redraws the column
Invalidate()
End If
' Hide the current Combobox when Focus on Combobox is lost
_cbo.Hide()
End Sub

I think that should cover most of it. My task was to create combobox display
different lists on different grid rows, so some of the code may not be
relevant, but it should not hurt either.

If the code above does not work or I have missed something again, let me know

Serge
 
D

Doug Bell

Thanks

Doug
Sergey Poberezovskiy said:
Doug,

_startEditing is a private variable that I initialise in the
comboconstructor - it refers to AddressOf selectionChangeCommit procedure in
DataGridComboboxColumn class.

Here is the constructor for the DataGridComboboxColumn:

Public Sub New()
' Create our own customized Combobox, which is used in the DataGrid
_cbo = New gridComboBox(AddressOf selectionChangeCommit)
_cbo.DropDownStyle = ComboBoxStyle.DropDownList
' GridComboBox subscribes to the Leave Event. It occurs when the
' input focus leaves the ComboBox.
AddHandler _cbo.Leave, AddressOf leaveComboBox
' GridComboBox subscribes to the SelectionChangeCommitted Event.
' It occurs when the selected item has changed and that change
' is committed (save the changed data to the DataGrid TextBox).
AddHandler _cbo.SelectionChangeCommitted, AddressOf selectionChangeCommit
End Sub

Now the actual procedure:
' The ColumnStartedEditing method allows the DataGrid
' to show a pencil in the row header indicating the row
' is being edited. (base is the parent DataGridTextBoxColumn)
Private Sub selectionChangeCommit(ByVal sender As System.Object, ByVal e As
System.EventArgs)
_editing = True
MyBase.ColumnStartedEditing(CType(sender, Control))
End Sub
And leave procedure:
' Handle Combobox Behaviour when Focus leaves the Combobox.
Private Sub leaveComboBox(ByVal sender As System.Object, ByVal e As
System.EventArgs)
If _editing Then
' Set the Combobox ValueMember to the current RowColumn
' when the Focus leaves the Combobox.
SetColumnValueAtRow(_currencyManager, _rowNum, _cbo.Text)
_editing = False
' Redraws the column
Invalidate()
End If
' Hide the current Combobox when Focus on Combobox is lost
_cbo.Hide()
End Sub

I think that should cover most of it. My task was to create combobox display
different lists on different grid rows, so some of the code may not be
relevant, but it should not hurt either.

If the code above does not work or I have missed something again, let me know

Serge
 

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

Similar Threads


Top