We inherited a control from UltraTextEditor overriding some of the OnXxx... methods. Several methods are beeing called in a very strange way:
OnEnter is beeing called recursive
OnLostFocus is called while OnGotFocus is active
OnGotFocus is only called, when the control looses focus, not when it gets the focus
Entering the control via mouse click triggers OnLostFocus
Moving the mouse over the control triggers OnMouseEnter immediately followed by OnMouseLeave
Moving the mouse away from the control triggers OnMouseEnter followed by OnMouseLeave
We want to offer the user an option to control selection behaviour if the control is entered with the possibility to distinguish if the control receives the focus by mouse click or through use of the Tab key. This does not seem to be possible the way OnXxx... methods are beeing called.
Below the sequence of "events" for the different situations:
OnEnter edt01 - StartOnEnter edt01 - Start (recursive call)OnEnter edt01 - End (recursive call)OnEnter edt01 - End
OnGotFocus edt01 - StartOnLostFocus edt01 - Start (nested call)OnLostFocus edt01 - EndOnGotFocus edt01 - EndOnGotFocus edt01 - StartOnGotFocus edt01 - EndOnLeave edt01 - StartOnLeave edt01 - EndOnLostFocus edt01 - StartOnLostFocus edt01 - End
OnMouseEnter edt01 - StartOnMouseEnter edt01 - EndOnMouseDown edt01 - StartOnEnter edt01 - Start (nested call)OnLostFocus edt01 - Start (nested call)OnLostFocus edt01 - EndOnEnter edt01 - Start (recursive call)OnEnter edt01 - End (recursive call)OnEnter edt01 - EndOnMouseDown edt01 – End
The mouse is still over the control while the following override is beeing calledOnMouseLeave edt01 - StartOnMouseLeave edt01 - End
OnMouseEnter edt01 - StartOnMouseEnter edt01 - EndOnMouseLeave edt01 - StartOnMouseLeave edt01 - End
OnLeave edt01 - StartOnLeave edt01 - End
Could there be anything we are doing wrong to cause this strange sequence of "events"?
RegardsBurkhard Exner
Burkhard,
These seemingly strange order of events are the result of the way that the UltraTextEditor was designed, in that when it is put into edit mode, a .NET TextBox is positioned within the bounds of the UltraTextEditor to handle the editing portion; when you exit edit mode, this control is removed. You can see when this occurs by listening to the ControlAdded and ControlRemoved events. There is also the following KB article:
FAQ:Mouse events such as MouseDown, MouseUp, and DoubleClick do not fire for an UltraWinEditor it is in edit mode.
Because of the way this is implemented, you'll see the various Enter/Leave/etc events fire for the UltraTextEditor when the TextBox is positioned, since the TextBox itself now has focus, and similar when you exit edit mode and the TextBox loses focus to be given to the UltraTextEditor.
-Matt
Matt.
Thank you for the information, it will allow us to achieve our goals.
In case you are interested I logged the events for the embedded control and still find them a bit confusing:
Enter is triggered twice
Leaving the control via TAB leaves, enters and leaves the control
OnEmbeddedEnterOnEmbeddedGotFocusOnEmbeddedEnter
OnEmbeddedLostFocusOnEmbeddedLeaveOnEmbeddedEnterOnEmbeddedGotFocusOnEmbeddedLostFocusOnEmbeddedLeave
OnEmbeddedEnterOnEmbeddedGotFocusOnEmbeddedMouseDownOnEmbeddedEnterOnEmbeddedMouseEnterOnEmbeddedClickOnEmbeddedMouseClick
OnEmbeddedMouseLeave
OnEmbeddedMouseEnter
OnEmbeddedLostFocusOnEmbeddedLeave
As a user of UltraTextEditor I think, the control should completely hide the fact that it works with an embedded TextBox and call OnXxx... methods and send events in a manner UltraNumericEditor and UltraMaskedEdit do. The current situation requires knowledge of UltraTextEditors implementation that might change in the future.
ThanksBurkhard
I think I had misunderstood what would happen with the UltraTextEditor, in terms of event firing. I know that it's a commone question regarding certain events and the UltraTextEditor (as outlined in the KB article I linked previously), but you shouldn't be getting multiple events fired for the same control's events. To test this out, I tried hooking the Enter and Leave of an UltraTextEditor; using both a mouse click and the Tab key to enter/leave the control only resulted in a single event for each action for me. Naturally, if I hooked the TextBox that's positioned within the control, I would hit more events.
What version of the controls are you using? I think that I recall an issue with events firing multiple times from a while ago, but I'm not completely certain on that. I attached the very simple sample that I used to test this to the project, so let me know if you're getting different behavior on your machine. For simplicity, I only hooked the Enter and Leave events, since you shouldn't really be relying on GotFocus/LostFocus.
Yet another misreading on my part that I realized right after posting this. I changed my sample to use a derived UltraTextEditor, since you're using the various On* events. I see the multiple calls that you're receiving in the OnEnter event, but there's not really anything we can do about this. The reason for this is also a side-effect of positioning the TextBox, but the OnEnter and OnLeave methods are triggered by the base Control class, so we don't have any control over when they're fired. In the case that I see, the first Enter is triggered by the control first becoming activated, while the second call is focusing the TextBox, since the TextBox is a child control of the UltraTextEditor (and so this call is done through ContainerControl.UpdateFocusedControl). You'll notice that the Enter event is only actually fired once.
The recursive call that you're seeing is because the UltraTextEditor knows that it needs to enter edit mode through the OnEnter message, so you are getting the recursive call to OnEnter for the reasons detailed above. The easiest solution is to simply keep a flag if you're in a recursive call and only do your processing once, i.e.:
private bool isInOnEnter = false;protected override void OnEnter(EventArgs e){ try { if (this.isInOnEnter) { base.OnEnter(e); return; } this.isInOnEnter = true; // Do stuff here // ... } finally { this.isInOnEnter = false; }}
Thank you for the background information. We got our derived control up and running. I hope Infragistics and Microsoft are working hard to never change the sequence of OnXxx-routines called :-).
Burkhard.
As an additional note, if you used my code above, you might want to move the block with "if(this.isInOnEnter)" outside of the try/finally block since that will always set the flag back to false, even if you're wihtin the recursive call.
I've ran into a number of issues with the "Ultra" controls which turn out to be caused by the underlying base control(s) that the Ultra control is built on top of. Personally, I'd MUCH rather see Infragistics build their OWN controls rather than just adding functionality to a base MS control. I mistakenly BELIEVED that's what I was getting when I purchased the NetAdvantage suite. I'm not very pleased to find that that is not the case...
How many of the "issues" would simply go away if Infragistics was using home built controls? How many could be FIXED to match what Infragistics customers want if they weren't based on MS controls? I realize they have to be .net compatible, but they don't have to use the MS controls as their base...
I could have sworn I originally included the base call in my test code, so I must have accidentally removed it when copy/pasting it. I guess I'm on a roll with flagrant oversights with this thread :-) You should definitely always be calling the base on any of these overrides. The flag simply lets you know if you're within the recursive call or not, but should otherwise not be changing any of the default behavior.
Thank you.
I already did that, but in comparison to your code I called base.OnEnter in the recursive call as well:
protected override void OnEnter (EventArgs e) { if (boOnEnterActiveC) { base.OnEnter (e); return; } boOnEnterActiveC = true; try { base.OnEnter (e); // Doing my stuff } finally { boOnEnterActiveC = false; } }
May this cause problems?
Burkhard