Fire comboBox SelectedIndexChanged only from user click - c#

I wrote a method to handle a comboBox's SelectedIndexChanged event.
In the constructor I populated the comboBox, and this activated my event-handling method. Which I don't want since nobody clicked on the comboBox.
Is there an easy way to get the comboBox not to fire the event unless the user clicked it?
If that is not possible, is there a way to disconnect the event to the method temporarily? Could I just set "my_combo.SelectedIndexChanged = null" and then create a new System.EventHandler?
Or I guess I could create some kind of boolean member variable that I can switch on or off and put a branch check in my method. That seems like a kludge, though.

I have done it a lot number of times.
Solution1: Delete EventHandler from designer. Populate the combobox and then set EventHandler.
Combo1.SelectedIndexChanged += new EventHandler Combo1_SelectedIndexChanged;
But it will work only if you are populating the combobox once.If you are doing it for many number of times, then you may be in a mess.
Solution2: Its my preference and I use it regularily.
Change your selection change event as:
private void cb1_SelectedIndexChanged(object sender, EventArgs e)
{
ComboBox cb = (ComboBox)sender;
if(!cb.Focused)
{
return;
}
// Here is your Code for selection change
}
So now the event will be fired only if its in focus. Hope you were looking for the same.
Hope it Helps

Not sure if this is any use now but I found this answer, which seems cleaner to me.
From the MSDN Library - ComboBox.SelectionChangeCommitted Event
"SelectionChangeCommitted is raised only when the user changes the combo box selection. Do not use SelectedIndexChanged or SelectedValueChanged to capture user changes, because those events are also raised when the selection changes programmatically."

You can use both methods You proposed:
use boolean variable
detach event method, populate combobox, attach event method like this
my_combo.SelectedIndexChanged -= my_Combo_SelectedIndexChanged;
populateCombo();
my_combo.SelectedIndexChanged += my_Combo_SelectedIndexChanged;
my_Combo_SelectedIndexChanged is the name of method you attached to the event.

I would use control.ContainsFocus instead of creating other bool. The caveat here is that you have to make sure the user has focus on that control. Either by key or mouse.
if(combo.ContainsFocus){ MyEventLogic();}

Solution: If you're populating combobox with static values only ones, just populate them and after subscribe to event from code. Do not use WinForms Designer to subscribe to it.
If it's not possible during loading can:
a) define a boolean variable bool loading, set it to true before you begin to populate combo with data, and in event handler check
if(loading)
return;
b) Unsubsribe from event:
If subscription was:
comboBox.SelectedIndexChanged += delegate(...);
Unsubscription before you begin load data is:
comboBox.SelectedIndexChanged -= delegate(...);
As loading of data finished, subscribe again.

Related

CheckedChanged not firing?

I have done a lot of reading on this and every question I found involves ASP.NET. I'm using Winforms. I have a checkbox (Called CheckboxPicture) on my main form. I want to run a few commands when the state of this checkbox is changed by the user.
This should do it:
public void CheckboxPicture_CheckedChanged(Object sender, EventArgs e)
{
MessageBox.Show("Check State Changed");
}
However checking and unchecking the checkbox dont work. ASP.NET says you need
Autopushback = true but I'm not useing ASP.NET so im not sure where that would go.
A google search for "winforms checkbox event" yields this as its first result:
MSDN: CheckBox.CheckedChanged Event
At some point, they mention:
To run the example code, paste it into a project that contains an instance of type CheckBox named CheckBox1. Then ensure that the event handler is associated with the CheckedChanged event.
(Emphasis mine.)
Unfortunately, they don't show how to "ensure that the event handler is associated with the CheckedChanged event".
In short, somewhere within your code you have to have the following statement:
CheckboxPicture.CheckedChanged += CheckboxPicture_CheckedChanged
In other words, your CheckboxPicture_CheckedChanged() method will not be called by magic, you have to make sure it gets called when the corresponding event of the checkbox is fired.
Go to the form in your designer. Click on the checkbox and look at the properties box. Click on the event handlers and select your handler for the CheckedChanged handler property.

ListView events set in the properties don't work

I am trying to use the MouseClick event from the properties of a listView to handle left and right mouse clicks.
Unfortunately the event never seems to fire. (Double clicked on the event to create a property, entered a bit of simple code and placed a breakpoint on the first line). The same is true of several other events listed in the properties (ItemSelectionChanged seems to work but the other events I have tried don't fire.
Here is the code added:
In form.designer.cs:
this.listView1.MouseClick += new System.Windows.Forms.MouseEventHandler(this.listView1_MouseClick);
In form.cs:
private void listView1_MouseClick(object sender, MouseEventArgs e)
{
Some code
}
That method never gets called when I click on the listview. The listview is inside a tab on top of the stack.
I guess I am probably forgetting something very basic but what?
ListView is a bit unusual, its MouseClick event doesn't fire unless you click an item in the view. Workaround is to use the MouseDown or MouseUp event instead. You typically are much more interested in the ItemSelectionChanged event btw. You probably need its HitTest() method to see exactly what was clicked if you use MouseDown/Up.

Is it possible to subscribe one control to the same event handler multiple times?

I would like to know if I bind the TextChanged event handler to a TextBox control, then how can I ensure that won't be allowed to bind this event handler again?
You can't ensure that. You would theoretically be allowed to bind the same event handler to a textbox (or other control) more than once. The only thing that events allow you to do is add a handler and remove a handler—there's no additional means provided to check for existing subscribers. If you don't believe me, Jon Skeet provides the authoritative answer here, and in his article on events.
If you need to ensure that you don't accidentally subscribe a control to the same event twice, you'll need to keep track of it yourself. Honestly, you should never end up in a situation where you don't know what event handlers are subscribed. Not only does this reflect sloppy design, but it probably also means that you aren't taking care to remove your event handlers when they are no longer necessary.
A possible solution is provided in the answers to this question, but I caution you from using something like this blindly. As others have argued, this code is something of an anti-pattern.
You can bind it programatically as many times as you'd like. If you want to prevent this you can use a List<object> to keep references in, for example:
private List gotRefs = new List();
public void MyMethod()
{
if (!gotRefs.Contains(txtTextBox1)) {
txtTextBox1.TextChanged += txtTextBox1_TextChanged;
gotRefs.Add(txtTextBox1);
}
}
You can actually use a hack.
You can make textbox private to your class to ensure, that only your single class is able to access the text box and add handlers to it.
private TextBox txtChanging;
Then, in your class, you can create a custom event like textBoxTextChanged
public event Action TextBoxTextChanged;
Create a standart method OnTextBoxTextChanged
private OnTextBoxChanged( object sender, EventArgs args )
{
if( TextBoxTextChanged != null )
TextBoxTextChanged();
}
Bind this OnTextBoxChangedMethod to TextChanged event of the TextBox
txtChanging.TextChanged += OnTextBoxChanged;
Ensure that NO OTHER METHOD is bound to TextChanged event of the text box
Bound all your main payload text changed handlers to your new custom event instead of text box textchanged event directly
TextBoxTextChanged += txtChanged_TextChnaged;
All that paperwork is because events actually provide a lot of information, but only to the methods inside the class where they are defined.
You can check bound delegates with
TextBoxTextChanged.GetInvocationList()
and their count with
TextBoxTextChanged.GetInvocationList().Count() //(C# 4.0/LINQ)
or just count them through foreach.

Textbox value changed

Is it possible to know if any of the textbox values have changed in the application.
I have around 30 textboxes and I want to run a part of code only if, any of the textboxes value has changed out of the 30. Is there a way I can know that.
Each text box will raise an event TextChanged when it's contents have changed. However, that requires you to subscribe to each and every event.
The good news is that you can subscribe to the event with the same method multiple times. The handler has a parameter sender which you can use to determine which of your 30 text boxes has actually raised the event.
You can also use the GotFocus and LostFocus events to keep track of actual changes. You would need to store the original value on GotFocus and then compare to the current value on LostFocus. This gets round the problem of two TextChanged events cancelling each other out.
You can assign an event handler to each of the TextBox's TextChanged events. All of them can be assigned to the same event handler in code. Then you'll know when the text changes. You can set a boolean flag field in your class to record that a change occurred.
This is perhaps on the rough and ready side, but I did it this way.
In the constructor, I created
bool bChanged = false;
In the TextChanged event handler of each control (actually same for each), I put
bChanged = true;
When appropriate, I could do some processing, and set bChanged back to false.
You can also just do this:
In your Constructor:
MyTextBox.TextChanged += new TextChangedEventHandler( TextChanged );
And Then this Method:
private void TextChanged(object Sender, TextChangedEventArgs e){
//Do something
}
try this. Add this code to the load/constructor. no need to specify the event in the XAML explicitly
this.AddHandler(TextBox.TextChangedEvent, new TextChangedEventHandler(TextChanged));
private void TextChanged(object Sender, TextChangedEventArgs e)
{
//ToDO (use sender to identify the actuale text from where it fired }
}

Issue in CheckedChanged event

I have a check box and I have subscribed for the CheckedChanged event. The handler does some operations in there. I check and uncheck the checkbox programmatically (ex: chkbx_Name.Checked = true), and the CheckedChanged event gets fired.
I want this event to be fired only when I manually check or uncheck it. Is there any way to avoid firing of this event when i check/uncheck it programmatically?
unsubscribe the event before you set:
check1.CheckChanged -= check1_CheckChanged;
then you can programmatically set the value without the checkbox firing its CheckChanged event:
check1.Checked = true;
then re-subscribe:
check1.CheckChanged += check1_CheckChanged;
[EDIT: March 29, 2012]
The problem with Tanvi's approach is you need to catch all source of manual check or uncheck. Not that there's too many(it's only from mouse click and from user pressing spacebar), but you have to consider invoking a refactored event from MouseClick and KeyUp(detecting the spacebar)
It's more neat for a CheckBox(any control for that matter) to be agnostic of the source of user input(keyboard, mouse, etc), so for this I will just make the programmatic setting of CheckBox really programmatic. For example, you can wrap the programmatic setting of the property to an extension method:
static class Helper
{
public static void SetCheckProgrammatically(
this CheckBox c,
EventHandler subscribedEvent, bool b)
{
c.CheckedChanged -= subscribedEvent; // unsubscribe
c.Checked = b;
c.CheckedChanged += subscribedEvent; // subscribe
}
}
Using this approach, your code can respond neatly to both user's mouse input and keyboard input via one event only, i.e. via CheckChanged. No duplication of code, no need to subscribe to multiple events (e.g. keyboard, checking/unchecking the CheckBox by pressing spacebar)
No. Those property change events fire whenever the property value changes, regardless of whether this was done by your code, by the control's own code or databinding. It's all the same code path, usually.
What you can do, however, if your event handler resides in the same class as the code that changes the property value, is to introduce a private boolean field in the class which you use as an indicator of whether the current property change is triggered by your code or by the user. After your change you simply reset it. The event handler would then look at the field and decide of whether it should do anything or not:
class Foo : Form {
private bool checkedProgrammatically = false;
void someMethod() {
// ...
checkedProgrammatically = true;
checkBox1.Checked = true;
checkedProgrammatically = false;
// ...
}
private void checkBox1_CheckChanged(object sender, EventArgs e) {
if (checkedProgrammatically) return;
// ...
}
}
I'm sorry I can't just comment on Michael Buen's answer due to my being new here (no reputation), but for what it's worth I strongly prefer his solution to Johannes Rössel's for a couple of reasons.
1) the checkedProgrammatically variable is a little too close to global for me. There's nothing to stop another method accidentally setting it to true, causing all your events to stop.
2) you could end up with a lot of variables depending on the number of events you're dealing with. It would be easy to change the wrong one and the results can be difficult to debug.
3) it's more obvious what you're doing when you unsubscribe then resubscribe. All the logic is right there, and you don't need to change your event handlers to exit early depending on certain conditions.
I've used both methods extensively and I find Michael's a lot easier in the long run.
You can use the MouseClick event and in that check for the checked state of the checkbox.
This way it wont be triggered programatically, it would only be called when the user manually checks or unchecks the checkbox.
You can set boolean variable before changing value programiticaly, and check than reset that variable in checkedchanged event

Categories

Resources