Event Order

W

Wayne Hartell

Hi there,

I was wondering how the SelectedIndexChanged event can fire in a ListView
control before the Leave event fires in the previous control that is losing
focus? Is this the designed behavior? I really need to be able to handle the
Leave event first and seeing validation events fire AFTER leave, it seems
that no events should fire in the list view until after the Leave even (and
validation events if not suppressed).

Kind Regards,
Wayne Hartell
 
W

Wayne Hartell

Further to this I set up a form with a ListView and a ListBox and can easily
demonstrate the difference in event order between the two.

The ListBox behaves as expected, with the SelectedIndexChanged occuring
after the Enter event. Not so for the ListView. The SelectedIndexChanged
events fire event before the Leave event for the ListBox, and sometimes more
than once!

I can provide a sample project if needed. This is under v1.1 of the
framework.

listView1_Enter
listView1_Leave
listView1_Validating
listView1_Validated
listBox1_Enter
listBox1_SelectedIndexChanged
listView1_SelectedIndexChanged
listBox1_Leave
listBox1_Validating
listBox1_Validated
listView1_Enter
listView1_Leave
listView1_Validating
listView1_Validated
listBox1_Enter
listBox1_SelectedIndexChanged
listView1_SelectedIndexChanged
listView1_SelectedIndexChanged
listBox1_Leave
listBox1_Validating
listBox1_Validated
listView1_Enter

Wayne
 
W

Wayne Hartell

Just one more piece of information. The TreeView control also seems to
suffer the same flaw. The AfterSelect event fires before the Enter event for
the control, thus not providing any hook/context for the programmer to do
something in the Leave event of the previous control.

Please tell me there is a solution.

Wayne.
 
C

Claes Bergefall

See inline

Wayne Hartell said:
Hi there,

I was wondering how the SelectedIndexChanged event can fire in a ListView
control before the Leave event fires in the previous control that is
losing

I don't see anything wrong with this. The SelectedIndexChanged event is
in no way dependent on any other control.

The SelectedIndexChanged event fires when you change the currently
selected item in the listview, any other behaviour would clearly be wrong.
It has nothing to do with the Leave event.

focus? Is this the designed behavior? I really need to be able to handle the
Leave event first and seeing validation events fire AFTER leave, it seems
that no events should fire in the list view until after the Leave even (and
validation events if not suppressed).

Validation events fires after the Leave event. This is by design and is
documented in MSDN. SelectedIndexChanged is not a validation event.
Kind Regards,
Wayne Hartell

/claes
 
W

Wayne Hartell

Hi Claes,

Thanks for the response, but I think you missed the point. I'm not
insinuating any relationship between events in different controls. I do,
however, believe the order of events is questionable in this case.

If control A has focus, and control B (a ListView) is clicked on, it seems
very wrong that the ListView's SelectedIndexChanged event would fire before:

a) The Leave event of control A, and any subsequent validation events for
control A
b) The ListView's own Enter event!

My way of thinking, as twisted as it may be, is that for a control to react
to a mouse click and fire SelectedIndexChanged it needs to have focus. I
read somewhere in the Windows API 101 that that's the way it works. The
window with focus receives the WM_ guys and it's WndProc deals with the ones
it wants and ignores the ones it doesn't. In this case it receives a mouse
click and changes the selected item. Given that the ListView must have focus
to respond to a mouse click, then it must have entered focus at some point,
which also means that the control with previous focus must have also lost
focus and been validated (if applicable). Now, why does the
SelectedIndexChanged event fire before a and b above?

This behavior is not the same for all other controls. e.g. the ListBox
control's SelectedIndexChanged event fires AFTER a and b above.

To me this event order is wrong and given the fact it is the way I would
expect for most controls, but out of order for the ListView and TreeView, it
seems something is not right.

In the use case I have, the contents of control A depends on the
SelectedIndex in the ListView. How am I to commit the data in control A, for
the index designated by the ListView's SelectedIndex when that SelectedIndex
changes even before I've had a chance to validate the contents of control
A?? You can't tell me that is the correct behavior.

Regards,
Wayne.
 
R

Rhett Gong

Hi Wayne:
From your event log, the ListBox behaves correctly.
Do you mean that the SelectedIndexChanged occurs after the Leave event
in ListView?
If yes,please send me your sample project for a test.
Just remove the online from my email address. Thanks!


Best regards,

Rhett Gong [MSFT]
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security

This posting is provided "AS IS" with no warranties and confers no rights.
 
W

Wayne Hartell

Hi Rhett,

Yes, the ListBox behaves correctly. I don't think the ListView does though;
it behaves differently to the ListBox.

The SelectedIndexChanged fires in the ListView even before the Leave (and
validation) for the ListBox and before Enter for the ListView.

I can send sample application if needed.

Thanks,
Wayne.
 
R

Rhett Gong

Hi Wayne:
Here is my event log:
//------------------------------------------------------
listView1_Enter
// step1:Click ListBox item
listView1_Leave
listView1_Validating
listView1_Validated
listBox1_Enter
listBox1_SelectedIndexChanged

// step2:click ListView item
listView1_SelectedIndexChanged
listBox1_Leave
listBox1_Validating
listBox1_Validated
listView1_Enter

// step3:Click ListBox item
listView1_Leave
listView1_Validating
listView1_Validated
listBox1_Enter
listBox1_SelectedIndexChanged

// step3:Click ListView item
// notice here is different , I clicked the same item as before.
listBox1_Leave
listBox1_Validating
listBox1_Validated
listView1_Enter
//-------------------------------------------------------

I write a program in MFC, the log is listed below:
//-------------------------------------------------------
ListControl--SelectChanged
ListControl--SetFocus
ListControl--SelectChanged
ListControl--SelectChanged
ListControl--SelectChanged
ListControl--KillFocus
ListBox--SetFocus
ListBox--SelectChanged
ListBox--KillFocus
ListControl--SetFocus
ListControl--KillFocus
ListBox--SetFocus
ListBox--SelectChanged
ListControl--SelectChanged
ListControl--SelectChanged
ListControl--SelectChanged
ListBox--KillFocus
ListControl--SetFocus
//-------------------------------------------------------
You can see that the MFC application behaves the same way as DotNet.
It is by design.
Can you detailed your request so that we can try to get a workaround for
you!

Best regards,

Rhett Gong [MSFT]
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security

This posting is provided "AS IS" with no warranties and confers no rights.
 
W

Wayne Hartell

Hi Rhett,

If it's by design that the ListBox behaves differently to the ListView (and
TreeView) then the design is flawed IMO. How can a developer rely on a
specific event order if it changes depending on which controls are being
used?

In your event log:

listView1_Enter
// step1:Click ListBox item
listView1_Leave
listView1_Validating
listView1_Validated
listBox1_Enter
listBox1_SelectedIndexChanged

// step2:click ListView item
listView1_SelectedIndexChanged
listBox1_Leave
listBox1_Validating
listBox1_Validated
listView1_Enter

I think the [// step2:click ListView item] is where
listView1_SelectedIndexChanged occurs before listBox1_Leave is a problem.
I'm not the only one at my company that thinks so.

The use case I need a solution for is as follows:

A control (a ListView or a TreeView) represents the view on a table. Then,
in the same dialog, the ListBox or other control represents the details of
the SelectedItem in the TreeView/ListView.

Like this:

// Manager with a list of items (Item 1 is selected)

ListView ListBox (or other control)
____________ ________________
| Item 1 | | Contents of Item 1 |
| Item 2 | | Contents of Item 1 |
| | | Contents of Item 1 |
____________ ________________

Now, the ListBox contents needs to be refreshed based on the ListView
selection... either Item 1 or Item 2 in this case.

If I now select Item 2 the SelectedItemChanged event fires immediately!!!
Thus I have no context or hook to commit or validate the data in the ListBox
since the SelectedItem changes in the ListView even before the Leave,
Validating and Validated events fire in the ListBox!

The work around I need is some context to commit (and/or validate) the data
BEFORE the SelectedIndex changes in the ListView. Basically, with the
current event order this is clearly not possible, yet if the ListView was
another ListBox or one of a number of other controls (including 3rd party
controls) that DO behave correctly, it all works fine. Why the ListView and
TreeView have to be different is quite frustrating.

I still can't see how this would be the expected behavior for the ListView
(and TreeView). Doesn't it feel wrong to you that the SelectedItemChanged
event fires at the response to a mouse click even before the control has
focus? Here we have a control receiving and responding to user input when
clients listening to the Enter and Leave events of the ListBox still would
assume that the ListBox has focus. Meanwhile the user is off interacting
with another control and manipulating its data.

Regards,
Wayne.







Rhett Gong said:
Hi Wayne:
Here is my event log:
//------------------------------------------------------
listView1_Enter
// step1:Click ListBox item
listView1_Leave
listView1_Validating
listView1_Validated
listBox1_Enter
listBox1_SelectedIndexChanged

// step2:click ListView item
listView1_SelectedIndexChanged
listBox1_Leave
listBox1_Validating
listBox1_Validated
listView1_Enter

// step3:Click ListBox item
listView1_Leave
listView1_Validating
listView1_Validated
listBox1_Enter
listBox1_SelectedIndexChanged

// step3:Click ListView item
// notice here is different , I clicked the same item as before.
listBox1_Leave
listBox1_Validating
listBox1_Validated
listView1_Enter
//-------------------------------------------------------

I write a program in MFC, the log is listed below:
//-------------------------------------------------------
ListControl--SelectChanged
ListControl--SetFocus
ListControl--SelectChanged
ListControl--SelectChanged
ListControl--SelectChanged
ListControl--KillFocus
ListBox--SetFocus
ListBox--SelectChanged
ListBox--KillFocus
ListControl--SetFocus
ListControl--KillFocus
ListBox--SetFocus
ListBox--SelectChanged
ListControl--SelectChanged
ListControl--SelectChanged
ListControl--SelectChanged
ListBox--KillFocus
ListControl--SetFocus
//-------------------------------------------------------
You can see that the MFC application behaves the same way as DotNet.
It is by design.
Can you detailed your request so that we can try to get a workaround for
you!

Best regards,

Rhett Gong [MSFT]
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security

This posting is provided "AS IS" with no warranties and confers no rights.
 
R

Rhett Gong

Hi Wayne:
When you click "Item1", you want the following scenario:
ListView ListBox (or other control)
____________ ________________
| Item 1 | | Contents of Item 1 |
| Item 2 | | Contents of Item 1 |
| | | Contents of Item 1 |
____________ ________________
When you click "Item2", you want this:
ListView ListBox (or other control)
____________ ________________
| Item 1 | | Contents of Item 2 |
| Item 2 | | Contents of Item 2 |
| | | Contents of Item 2 |
____________ ________________
Am I right?
I think you can add items dynamically to ListView2.
Here is a code snippet to show that.
Note: I used 2 listview control in my application.
//--------------------------------------------------------------------------
----

private void listView1_SelectedIndexChanged(object sender, System.EventArgs
e)
{
int index = listView1.FocusedItem.Index;

if( index == 0)
{
listView2.Clear();
listView2.Items.Add("Hello1");
listView2.Items.Add("Goodbye1");
}
if( index == 1)
{
listView2.Clear();
listView2.Items.Add("Hello2");
listView2.Items.Add("Goodbye2");
}

}
//--------------------------------------------------------------------------
-------------------

Rhett Gong [MS]
Microsoft Online Partner Support

This posting is provided "AS IS" with no warranties, and confers no rights.
Please reply to newsgroups only. Thanks.
 
W

Wayne Hartell

Hi Rhett,

Thanks for the snippet, but its not quite that simple for my use case! :)

I'm living in a world of multi-tiered application framework with
UI/Application/Adapting/Domain/Data layers all to deal with. The ListView
could be one form, and the ListBox another. The forms could be modal or
modeless. I can't make any assumptions about where these controls will be,
what data they will possess or even which controls will be used :) All I
know is that if the ListView is used, the code doesn't work anymore.

Anyway, in the context of our framework we have developed a work around to
the problem. We were kind of hoping we wouldn't need to, but can appreciate
that the behavior has been that way and will remain to be that way.

I appreciate all of your help.

Thanks,
Wayne.
 

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