tags:

views:

64

answers:

3

I have a bunch of controls on a form and all of their "change" events point to the same event handler. Some of these are txtInput1's TextChanged, chkOption1's CheckedChanged, and cmbStuff1's SelectedIndexChanged. Here is the event handler:

private void UpdatePreview(object sender, EventArgs e)
{
    // TODO: Only proceed if event was fired due to a user's clicking/typing, not a programmatical set
    if (sender.IsSomethingThatTheUserDid) // .IsSomethingThatTheUserDid doesn't work
    {
        txtPreview.Text = "The user has changed one of the options!";
    }
}

I would like the if statement to only run when a user changes the TextBox text or clicks a checkbox or whatever. I don't want it to happen if the text or checkbox was changed by some other part of the program.

+5  A: 

There isn't a built-in mechanism to do this. You can, however, use a flag.

bool updatingUI = false;

private void UpdatePreview(object sender, EventArgs e)
{
    if (updatingUI) return;

    txtPreview.Text = "The user has changed one of the options!";
}

Then, when you're updating the UI from your code:

updatingUI = true;

checkBox1.Checked = true;

updatingUI = false;

If you want to over-engineer the solution, you could use something like this:

private void UpdateUI(Action action)
{
    updatingUI = true;

    action();

    updatingUI = false;
}

And use it like this:

UpdateUI(()=>
{
    checkBox1.Checked = true;
});
Adam Robinson
Thanks, I was just assuming that there was a built-in mechanism to do this. I'll use a flag. Plus I learned something new with the syntax in your last code block :)
Coder7862396
@Coder: It's called a lambda expression. You should find plenty of information about them. Good luck!
Adam Robinson
A: 

Can't you just check the sender? If it's called from a wired event to a UI control, it will come back with the control. If you're firing the event from code, it will either be the component making the call, or you could make it anything you want:

private void SomewhereElse()
{
   UpdatePreview(null, new EventArgs());
}

private void UpdatePreview(object sender, EventArgs e)
{
    if (sender == null) 
    {
        txtPreview.Text = "The user has changed one of the options!";
    }
}

or you may be able to do this:

private void UpdatePreview(object sender, EventArgs e)
{
    if (!(sender is Control)) 
    {
        txtPreview.Text = "The user has changed one of the options!";
    }
}
Robaticus
This is incorrect. The sender is always the object raising the event. Regardless of whether the `Text` property was changed by input or by code, the `sender` variable will always be the instance of the textbox that raised the event.
Adam Robinson
It's not "UpdatePreview()" that is being called from somewhere else, it's the setting of the text or checkbox (txtInput1.Text = "Hello from somewhere else")
Coder7862396
@Adam - This is incorrect from the standpoint of answering the posted question. I had misread what he was trying to do. My answer is correct within the context that I posted. @Coder7862396 - You're absolutely right. I missed that in the original posting.
Robaticus
@Robaticus: I understand what you're getting at, but you said "firing the event from code". Calling the event handler is not the same thing as firing the event; the only way to fire the event is to do something to the control to get it to fire the event, which means that the answer is incorrect (`sender` will always refer to the sending control when the event is fired/invoked, regardless of source).
Adam Robinson
A: 

Try to go up the call stack and analyze it in some way (system.diagnostics). But keep in mind it's somewhat tricky and hacky.

"From code": From code

User-triggered: User-triggered

Entrase