Hi,
I have a problem whith the ultraGrid.I am editing a string field, and while still editing, I click outside the grid such as I gice the focus to another component.The gridLostFocus event is not raised. (If I am editing in an UltraNumericEditor it works fine).Is that a know problem, or do I do something wrong ?
Thanks
Anne-Lise
Hi Anne-Lise,
What component outside the grid are you clicking on? Not all components take focus. If you click on a toolbar button, for example, the grid will not lose focus.
In any case, I would strongly recommend that you do not use LostFocus or GotFocus events on any control. These events are tied directly to Windows messages and they will give you all sorts of unexpected results. Microsoft's documentation advises against using them in DotNet, also. You should use Enter and Leave, instead.
It occurs with different sort of components which take focus:
If I use a ultraNumericEditor to edit in my cell it works (Grid lostFocus is correctly sent), but if I use default behavior to edit in cell or a ultraTextEditor it does not works (Grid lostFocus is not sent when another component take the focus).
Hi Mike,
I am having a similar problem where my value is not being committed to the bound data object when I click a toolbar button while the cell is still in edit mode.
To try and fix this, I have placed an UltraTextEditor in all my string columns as so:
private void OnInitializeLayout(object sender, InitializeLayoutEventArgs e) { foreach (UltraGridBand band in e.Layout.Bands) { foreach (UltraGridColumn column in band.Columns) { if (column.DataType == typeof(string)) { column.EditorComponent = this.textEditor; column.UseEditorMaskSettings = true; } } } }
And I initialize my text editor as so:
this.textEditor = new UltraTextEditor(); this.textEditor.Leave += TextEditor_Leave;
However, when I am editing text and then click on a toolbar button, the leave event never gets fired. Do you have any idea why this might not happen?
I am using a custom table that derives from an ultragrid that automatically adds default editors based on value type, and if I do not change the editor, the above problem does not happen because the grid's lose focus event is fired which the custom class handles and calls
this.PerformAction(UltraGridAction.ExitEditMode);
However, as soon as I change the editor components from their initial states (I need to do so because the custom table uses a formatted text editor which replaces special chars with their html representation), the lose focus event no longer gets fired and I cannot seem to find a way to apply any changes to the data source for the above scenario. I have noticed that when I click between cells that have the above text editor, the grid's lose focus event gets fired, however when I click between cells with the original editors, the lose focus event does not fire. However, I cannot find any code in the custom implementation that would create that behavior. All that code does is instantiate the editors once and apply them to the columns in the same way I do above. Do you have any ideas of what I could try to address this issue?
The grid commits the changes and updates the data source when it loses focus. This is by default, although you can change this behavior via the UpdateMode property.
The reason it doesn't work when you click a toolbar button is that toolbar buttons do not take focus. Therefore, the grid never loses focus in this case.
The simplest solution is to simply call grid.UpdateData when the toolbar button is clicked. That will force the grid to commit as though it had lost focus.
Although unsatisfactory, I think that might be the easiest solution. What is strange, is the grid does lose focus when I click the toolbar buttons after editing a cell with a numeric editor instantiated by the custom ultra grid class that mine inherits from.
Just because I'm curious, the solution you propose seems like a bad practice for MVVM applications since the grid code should be handled in the view and the button click should be handled in the view model, therefore the button click should not be aware that the view is using an ultragrid. Do you have a preferred method of handling this sort of thing (I would imagine this is a very common problem) in an MVVM structure?
Tanner Stevenson said:Although unsatisfactory, I think that might be the easiest solution. What is strange, is the grid does lose focus when I click the toolbar buttons after editing a cell with a numeric editor instantiated by the custom ultra grid class that mine inherits from.
It depends on the editor, but if the particular editor in question is showing a child control (like a Textbox) on top of the grid, then the grid itself would lose focus when that cell ENTERS edit mode. But I can't think of any reason why the grid would lose focus when you click a toolbar button unless something in your code is doing that, or something in the toolbar button is setting focus to something outside the grid - or maybe changing the active cell.
Tanner Stevenson said:Just because I'm curious, the solution you propose seems like a bad practice for MVVM applications since the grid code should be handled in the view and the button click should be handled in the view model, therefore the button click should not be aware that the view is using an ultragrid. Do you have a preferred method of handling this sort of thing (I would imagine this is a very common problem) in an MVVM structure?
MVVM doesn't really apply to Windows Forms. That's more of a WPF concept. I can't claim to be any kind of expert on MVVM, since I mostly do WinForms, but since both the grid and the toolbar are in the UI, I don't really see a conflict there. Why should the button click be handled in the View Model? The button click is part of the UI, it's not the business logic.
So while doing some investigation, it seems the underlying difficulty I am facing is that an UltraTextEditor is built in an entirely different way than a UltraNumericEditor or a UltraFormattedTextEditor. This difference leads to a completely different handling of gaining focus and losing focus. I verified that my toolbar button does gain focus when it is clicked (may be a wpf thing), and the if an UltraFormattedTextEditor or UltraNumericEditor is currently focused, the grid will fire a LostFocus event when that button is clicked. However if a UltraTextEditor is currently focused, the grid will not send that event, for whatever reason. Alternatively, if I simply set the editor component to null, the behavior is the same as if I set it to an UltraTextEditor. So since all of these issues came to light simply because I wanted to save character literals to my data objects, one way to solve my problem in a "nice" way would be to simply allow character literals through the UltraFormattedTextEditor. Do you know of any way to that? I have searched exhaustively to no avail.
Mike Saltzman said:Why should the button click be handled in the View Model? The button click is part of the UI, it's not the business logic.
The event that happens because of the button click is the business logic, so the button's command is bound to a command in the view model. The view does not subscribe to any button click events.
I think that's correct, yes. It would certainly explain all of the behaviors you are getting.
Okay so the real confusion then is the word "focus" and even though a form of "focus" is placed on the button, it is not the type that is necessary to throw the Leave event. Would you agree?
Well, thank you for your time and help.
Hi Tanner,
My guess is (and I say guess because we're really talking about the DotNet Framework here and not the Infragistics controls any more) that since the Toolbar is a separate windows and the GotFocus and LostFocus are tied to windows messages that as far as Windows is concerned, the toolbar gets focus. But that's not the same kind of focus we're talking about when we talk about focus in DotNet. Which is why, once again, Microsoft's documentation recommends using Leave and Enter and not using GotFocus and LostFocus.
If the toolbar button does not gain focus, why then is the GotFocus event thrown when the toolbar button is clicked?
Tanner Stevenson said: I realized that the Leave event doesn't get thrown with either editor, but the grid's lost focus event does get thrown with the UltraFormattedTextEditor.
Okay... well, that makes perfect sense and it's one of the main reasons why using the LostFocus event is NOT a good idea. LostFocus is tied to the Windows messages. When a grid cell with a FormattedTextEditor is in edit mode, the grid has focus. Therefore, when you click on some other control, the grid loses focus.
But, if the grid does not have focus, because it contains a child control (like a TextBox) which is what happens when a regular text cell has focus, the event will not fire. It doesn't fire because the grid didn't lose focus, because the grid didn't HAVE focus. The TextBox did.
If you really want to jump through these kinds of hoops to make this work, then you could handle the grid's ControlAdded event and hook the LostFocus event of the child controls that are added to the grid. You would, of course, also want to unhook the event in ControlRemoved. But this isn't going to work very well for that you want, either, because the TextBox will lose focus when you leave one grid cell and move to another one, for example. In such a case, the TextBox loses focus and the grid gets focus.
This complexity with child control is why it's not a good idea to rely on GotFocus and LostFocus in DotNet for WinForms. The Enter and Leave events take care of all the child controls for you so you don't have to worry about it. Of course, they only fire when another control actually takes focus, and as we've already covered, the Toolbar buttons don't.
So after all this, we are basically back where we started. The simplest and easiest way for you to solve this problem is to simply call UpdateData on the grid in the click event of your toolbar button.