ComboBox and SelectedIndex Firing unexpectedly

J

Joe

Hi

I am adding a class to a ComboBox - and all is fine except that I fill the
combobox on the
Form_Load Method and it causes the method
private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)

To fire twice
Once when I comboBox2.DataSource = allMonths;
And again when I execute comboBox2.DisplayMember = "Name";

Anybody seen this - I want to detect when a selection has changed in the
combobox - should I use another method??

{

Form1_Load

{

ArrayList allItems = new ArrayList();

allItems.Add(new TypePair("Item1", 1));

allItems.Add(new TypePair("Item2", 2));

allItems.Add(new TypePair("Item3", 3));

allItems.Add(new TypePair("Item4", 4));



comboBox2.DataSource = allItems;

comboBox2.DisplayMember = "Name";

comboBox2.ValueMember = "ID";

}




}

private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)

{

MessageBox.Show(comboBox2.SelectedValue.ToString());

}



}

class TypePair

{

string m_Name;

int m_ID;

public string Name

{

get{ return (m_Name);}

set { m_Name = value; }

}

public int ID

{

get { return (m_ID); }

set { m_ID = value; }

}


public TypePair(string name, int nID)

{

this.m_Name = name;

this.m_ID = nID;

}



public override string ToString()

{

return m_Name;

}



}
 
D

Dave Sexton

Hi Joe,

You should set the DisplayMember and ValueMember properties before you set the DataSource property.
 
J

Joe

Hi Dave

Thanks - your suggestion removed 1 of the 2 firings of SelectedIndexChanged

Is this just an unexpected effect of using a combobox this way ???

Thanks
 
D

Dave Sexton

Hi Joe,

The behavior you witnessed from the ComboBox by setting the properties out of order is expected. Once you set the DataSource
property the control is bound immediately. If you then set a binding configuration property such as DisplayMember, the ComboBox has
to rebind in order to display the new text. I'm not sure why the SelectedIndexChanged event is firing though but I'd imagine it's
because the ComboBox resets some internal state pre/post binding.

Rule of thumb would be to set binding configuration properties before assigning the source on all controls that support data binding
with binding configuration properties, wherever possible.
 
A

Alan Pretre

Dave Sexton said:
I'm not sure why the SelectedIndexChanged event is firing though but I'd
imagine it's because the ComboBox resets some internal state pre/post
binding.

Actually, it is normal for some controls to fire events when loaded
programatically as if a user had interacted with the control. The only
reliable way I have found to get around this across all controls is to use a
form-level boolean called IgnoreEvent that the event handlers check.

For example,

At the class level:
bool _IgnoreEvent = false;

In some method:
bool SavedIgnoreEvent = _IgnoreEvent;
_IgnoreEvent = true;
<Set control property here>
_IgnoreEvent = SavedIgnoreEvent;

First thing in some event handler:
if (_IgnoreEvent) return;


Some vendors/controls may treat programmatic setting of properties different
than user interaction, it just depends on them. Others may provide a
BeginUpdate property or somesuch that turns off event firing. In many cases
these events are firing and the developer doesn't realize it because a
problem has not shown up. Tracing through the app, however, shows these
extraneous events during initialization.

At some point, it's a good idea to set breakpoints in all event handlers of
a working WinForm and just watch the events being thrown. This IgnoreEvent
trick can help eliminate redundant work done by the handlers.


-- Alan
 
D

Dave Sexton

Hi Alan,
Actually, it is normal for some controls to fire events when loaded programatically as if a user had interacted with the control.
The only reliable way I have found to get around this across all controls is to use a form-level boolean called IgnoreEvent that
the event handlers check.

I don't believe that the ComboBox raising the SelectedIndexChanged event when the DisplayMember property is set reflects any type of
intuitive user interaction with the Control and even if it's normal for some controls to behave like this, not all controls will.

I believe there is a more reliable way to handle the op's scenerio, as I suggested.

[snip]
Some vendors/controls may treat programmatic setting of properties different than user interaction, it just depends on them.
Others may provide a BeginUpdate property or somesuch that turns off event firing. In many cases these events are firing and the
developer doesn't realize it because a problem has not shown up. Tracing through the app, however, shows these extraneous events
during initialization.

It is common practice to set the DataSource property last when binding. I'd much rather ensure that the properties are being set in
a standardized order rather than trying to debug or manage state with a global field and tracing. For this reason I don't think it
really matters why the SelectedIndexChanged even is raised when the DisplayMember property is set after the DataSource property.
At some point, it's a good idea to set breakpoints in all event handlers of a working WinForm and just watch the events being
thrown. This IgnoreEvent trick can help eliminate redundant work done by the handlers.

I'd much rather set the DataSource property last and expect that the events will fire only once. The behavior of data binding
controls is predictable when used in this manner.
 

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