By Charles R Hankey - 6/1/2010
This is both interesting and frustrating ( like so many things in our profession )
In the example the only change i have made to Ivan's clever trick of placing the UG in a groupbox which handles the TabOrderController is to put that groupbox on a TabPage ( and are all the ultragrids in my app )
ctrl-Tab seems reserved to move between tab pages. But ctrl-E is also a problem. Not sure where the focus goes, since in watch window it shows e.keycode is not keys.E but CntrlKey {17} ( this is also true when it is Cntrl-TAB )
Oddly, Ctrl-A, Ctrl-X etc work as expected. And my code in the OnKeydown to have cntrl-Delete delete the row works fine, so I am not sure how the keycode is getting intercepted by the TabControl..
Notice in the sample that if the TabControl is removed, the groupbox/ultragrid work exactly as in the original example.
I have not been able to figure out if this is a SF thing or just a .NET tabcontrol thing or where to intervene.
If it is not fixable I need to convert my app to use panels or something instead but before I go that direction I'd like to know this can't be fixed and that I am not going to have the same problem there.
Thanks in advance ( Ivan )
|
By Ivan George Borges - 6/1/2010
Hi Charles.I'm out of office right now and won't be able to test your sample fully, but one thing I noticed after a quick look is that on my original sample, I was dealing with keystrokes on the BaseForm, overriding the ProcessCmdKey, while you are dealing with it inside your BaseGrid. Guess that this could make a difference. Talk to you later.
|
By Charles R Hankey - 6/1/2010
There is no override of ProcessCmdKey anywhere in your sample but that seems to be the right direction. I tried this code in the MyBaseUltraGrid.vb
Protected Overloads Overrides Function ProcessCmdKey(ByRef msg As Message, ByVal keyData As Keys) As Boolean
Const WM_KEYDOWN As Integer = &H100
Const WM_SYSKEYDOWN As Integer = &H104
If (msg.Msg = WM_KEYDOWN) OrElse (msg.Msg = WM_SYSKEYDOWN) Then
Select Case keyData
Case (Keys.Control Or Keys.Tab)
SetFocusToNextControl(True)
Exit Select
Case (Keys.Control Or Keys.E)
SetFocusToNextControl(True)
Exit Select
End Select
Return (MyBase.ProcessCmdKey(msg, keyData))
End If
End Function
but just like the onkeydown code it is showing e.keycode as Contrlkey {17}
I've tried intercepting the keydown in the tabcontrol and tabpage but don't seem to have that figure out either.
It is definitely a problem with the tabcontrol (or page) catching the keystroke before it hits the Ultragrid but I'm in over my head on the process of events.
|
By Charles R Hankey - 6/1/2010
Sorry Ivan, I'm being an idiot. i went back to the original thread and saw the code you posted about processcmdkey.
I'll work with that and hopefully I can have this working by the time you get back to the office
|
By Charles R Hankey - 6/2/2010
Well, no joy so far. ProcessCmdKey gets the same results. I also have not been able to get to work using a panel manager instead of TabControl.
I think I need to subclass the TabControl and let the ctrl-TAB pass through to the grid as some of the other Ctrl combinations do ( my cntl-Delete I created works fine - Ctrl-E does not ) I thought it might be in the SF TabControl but there is no code in the SF controls handling keystrokes.
I have tried overriding ProcessCmdKey at the tabcontrol level to just return and not call the baseclass if the key combo is ctrl-tab but that doesn't work
The processcmdkey on the baseform still sees the the TAB as controlkey if it is combined with control ( just as the onkeydown does )
I'm really stuck and the interface pretty much depends on this working ( have a question up on Stackoverflow but no answers yet )
|
By Ivan George Borges - 6/2/2010
Yeah, I have been playing with it a lot too, but it is quite difficult to control this situation. Anyway, I got a bit near... since you've got Infragistics, I used the UltraTabControl instead, and the reason was that I could set a mneumonic to its tab names, like Tab&1, Tab&2, which will show Tab1, Tab2. I also set the TabStop for the control as False. This way, you could tell your users that they need to Alt+1, Alt+2 and so on, using the mneumoics you assigned to the Tabs, to get them focused, and then the Tab key would allow them to navigate inside the controls you drop in each page, your UltraGrid for instance. To get out of them, they Alt+X the page again and use the ****+Tab to go to the previous control, and then Tab through the other controls outside the UltraTabControl as they wish... What about that?
|
By Ivan George Borges - 6/2/2010
Hey, the **** should be S h i f t ... but I might have spelt it wrongly.
|
By Charles R Hankey - 6/2/2010
Not sure I understand. Moving between tab pages isn't the problem. I just need to subclass the tab control to completely ignore key input just as the form does, no? I will look at the ultratab to see if I can turn it off there.
Somewhere a tabcontrol is handling control tab and I think all I need to do is convince it to ignore it.
I'll read your reply over a couple of times to see if I'm getting it but I may end up just finding a combination that is *not* blocked by tabcontrol and using that. So far I know ctrl-tab and ctrl-E won't work.
Maybe Stackoverflow will come to the rescue ...
It just seems it should be easier than this, given the granular control we have over most of the .net events.
|
By Charles R Hankey - 6/2/2010
Actually, it is kind of easy. ( or at least the 90% I have so far is )
First, the ctrl-tab handled by the tabcontrol has to be disabled. In the subclass of TabControl :
Public Class MyTabControl
Inherits MicroFour.StrataFrame.UI.Windows.Forms.TabControl
Protected Overrides Sub OnKeyDown(ByVal e As System.Windows.Forms.KeyEventArgs)
If e.KeyCode = Keys.Tab AndAlso e.Control Then
e.Handled = False
e.SuppressKeyPress = False
Else
MyBase.OnKeyDown(e)
End If
End Sub
End Class
This allows the cntrl-tab to fire in the Ultragrid and to actually leave the grid and the groupbox. The problem is, I can't tell where it goes next. the next control doesn't get focus, but tab again and the control after that gets focus, so it did honor the tab order but somehow lost energy for focusing.
But if I explicitly call the focus() of that next control in the tab order in groupbox.leave everything is good.
Private Sub GroupBox1_Enter(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles GroupBox1.Enter
Me.grdCustomers.Focus()
End Sub
Private Sub GroupBox1_Leave(ByVal sender As Object, ByVal e As System.EventArgs) Handles GroupBox1.Leave
Me.Textbox2.Focus()
End Sub
For now, this will work, though I want to make it generic and actually have a subclassed groupbox that knows how to set focus to its contained ultragrid on Enter and set focus to the next control according to the TabOrderController on Leave.
I'll be working on it more but here is it so far
|
By Ivan George Borges - 6/2/2010
Brilliant, Charles! Great to hear you got it working.
|
By Charles R Hankey - 6/2/2010
Actually we got it working
It turns out my code to override the tabcontrol and to set focus coming out of the groupbox was the right thing.
But your baseform code in ProcessCmdKey was what was actually making it leave the grid. That is the right place to put it ( though it still seems to have the problem of not knowing where to go next )
I took out your baseform code and it stopped working. Put it back in, took out my Ultragrid onkeydown code for the navigation and it still works.
Oh, and I subclassed groupbox to call me.controls(0).focus() on Enter to be used where it just contains a grid. Created a property NextControl ( string ) and am trying to figure out how to say, in the Leave of the groupbox class "Set focus to the control named NextControl"
Here's the latest
|
By Greg McGuffey - 6/2/2010
Charles is like a kid in a candy store.....
|
By Edhy Rijo - 6/2/2010
Greg McGuffey (06/02/2010)
Charles is like a kid in a candy store.....
That is a common effect from SF
|
By Ivan George Borges - 6/7/2010
By the way, since we are in this UltraGrid marathon, have you been dealing with date columns on the grids? I am going nuts trying to duplicate the DateTimePicker behavior where 1/1/1800 should show empty date and entering empty date should save 1/1/1800 to the table.
|
By Charles R Hankey - 6/8/2010
I only have one data field in my grid which defaults to now() so I didn't realize it was a problem until you mention it and I try to blank the date.
I just tried using an SF wrapper UltraDateTimePicker as an editor component and at least the error message is different. When I blank the field in the grid I get an error that i have violated the minimum on the datetimeconstraint and the date is set to 01/01/0001
I think modifying an editorcomponent is going to be the way to go, but haven't worked it out yet. Perhaps modifying the SF picker control to implement that interface Infragistics says is necessary to use a control in an Ultragrid ? Or just using a straight winforms datetime picker and implementing that interface as well as the logic that SF uses to blank dates on null?
|
By Ivan George Borges - 6/9/2010
Yep, guess we have this ahead of us. The SF wrapper UltraDateTimePicker works just fine on itself, but when we set it to be the column editor, no luck.
|
By Charles R Hankey - 6/9/2010
I have not been able to figure out where to intervene to translate the null in the control to #1/1/1800# in the BBS.
There is a BeforeRowUpdate and AfterRowUpdate and I can test for e.row.cells("DateofSale").value and there is a .setvalue method but I don't see how to change the data coming from the BBS to a null if it is #1/1/1800# and to change it back on the update.
I don't have source, so I'm poking around in the dark. Have a question up on StackOverflow but didn't have any luck there on my last Ultragrid question. The tech support guy on the Infragistics forum really doesn't seem to have his heart in it and doesn't answer questions very well. A couple of people have asked questions like this and his answers have not been helpful.
Anybody know if DevExpress grid has this problem? I have their trial right now and considering switching over.
|
By Ivan George Borges - 6/9/2010
I was dealing with other things around here, back to the matter. I have also posted your question in the Experts Exchange forum and will get back to it now. The first to accomplish this gives a shout!
|
By Charles R Hankey - 6/9/2010
I seems the question we really need to ask is : How do we display the date #1/1/1800# as if it were null. And how do we save null to the datasource/bbs as #1/1/1800#
The answers people seem to give seem to always start with telling you you can't have null dates in .NET ( which we know ) but they don't know about our framework's handling nulls as #1/1/1800#
|
By Ivan George Borges - 6/9/2010
Hi Charles.I think I found a way to handle this, not sure you will like it, but it seems to be working. The idea is to add an unbound column to you grid, you can do that with the grid designer clicking on the "Add Unbound Column" button at the Columns treeview item. Give it a Key name, like ubc_Date. Set its DataType to System.DateTime. We will use this unbound column to store your date from the table. Have a look at the code and let me know. #Region " Private Fields " '-- keep current cell state Dim _CellUpdating As Boolean = False #End Region #Region " Handled Events " Private Sub grdYourGrid_InitializeRow(ByVal sender As Object, _ ByVal e As Infragistics.Win.UltraWinGrid.InitializeRowEventArgs) _ Handles grdYourGrid.InitializeRow '-- check if there are rows to be initialized If Me.grdYourGrid.Rows.Count() = 0 Then Exit Sub End If '-- move record point to current row YourTableBO1.SeekToPrimaryKey(e.Row.Cells("yt_pk").Value) '-- if cell is updating, don't set unbound column If _CellUpdating = False Then '-- if underlying table has #1/1/1800#, show empty cell for date If YourTableBO1.yt_Date = #1/1/1800# Then e.Row.Cells("ubc_Date").Value = DBNull.Value Else e.Row.Cells("ubc_Date").Value = YourTableBO1.yt_Date End If End If '-- reset the flag _CellUpdating = False End Sub Private Sub grdYourGrid_AfterCellUpdate(ByVal sender As Object, _ ByVal e As Infragistics.Win.UltraWinGrid.CellEventArgs) _ Handles grdYourGrid.AfterCellUpdate '-- if unbound date column, deal with empty date If e.Cell.Column.Key = "ubc_Date" Then If e.Cell.Value Is DBNull.Value Then YourTableBO1.yt_Date = #1/1/1800# Else YourTableBO1.yt_Date = CDate(e.Cell.Value) End If End If '-- set the cell state to updating _CellUpdating = True End Sub #End Region
|
By Ivan George Borges - 6/9/2010
Ah, forgot to say... set the actual date column Hidden property to True.
|
By Charles R Hankey - 6/9/2010
YOU ARE MY HERO !
I will test this tonight and let you know
|
By Charles R Hankey - 6/9/2010
While I'm testing your solution, here's the response I got on StackOverflow. I'm thinking there might be a way to put an UltraDataSource between the BBS and the grid ?
Do you have an UltraDataSource backing your grid? If so, then e.Row.ListObject should be the UltraDataRow corresponding to the grid's row.
I often keep a reference to a business object in the UltraDataRow's Tag property, and I end up with InitializeRow methods that look like this (apologies for C# instead of VB.net):
private void mygrid_InitializeRow(object sender, InitializeRowEventArgs e)
{
try
{
UltraDataRow udr = e.Row.ListObject as UltraDataRow;
if (udr == null)
{
return;
}
MyRecord rec = udr.Tag as MyRecord;
if (rec == null)
{
return;
}
...
You can also access the underlying datasource values from udr.Band.Cells.
Hope this helps!
|
By Charles R Hankey - 6/9/2010
Você é um gênio e você é meu herói
|
By Charles R Hankey - 6/9/2010
Works beautifully ! ( though I was less successful in putting formatting for font, size and bold around the Portugese - some it got post before I could switch to English )
this will definitely solve my immediate issues and really isn't difficult to implement wherever I need dates in an Ultrawingrid
Wow. I'm impressed
|
By Ivan George Borges - 6/10/2010
Charles R Hankey (06/09/2010) While I'm testing your solution, here's the response I got on StackOverflow. I'm thinking there might be a way to put an UltraDataSource between the BBS and the grid ?
Well, at least you got an answer over there, Experts Exchange didn't get me any.
|
By Ivan George Borges - 6/10/2010
Charles R Hankey (06/09/2010)
Você é um gênio e você é meu herói Oh, that is perfect Portuguese! Thank you for your kind words, Charles. Really glad it worked.
|