views:

1262

answers:

4

Is there any way for the main form to be able to intercept events firing on a subcontrol on a user control?

I've got a custom user-control embedded in the main Form of my application. The control contains various subcontrols that manipulate data, which itself is displayed by other controls on the main form. What I'd like is if the main form could be somehow informed when the user changes subcontrols, so I could update the data and the corresponding display elsewhere.

Right now, I am cheating. I have a delegate hooked up to the focus-leaving event of the subcontrols. This delegate changes a property of the user-control I'm not using elsewhere (in this cause, CausesValidation). I then have a delegate defined on the main form for when the CausesValidation property of the user control changes, which then directs the app to update the data and display.

A problem arises because I also have a delegate set up for when focus leaves the user-control, because I need to validate the fields in the user-control before I can allow the user to do anything else. However, if the user is just switching between subcontrols, I don't want to validate, because they might not be done editing.

Basically, I want the data to update when the user switches subcontrols OR leaves the user control, but not validate. When the user leaves the control, I want to update AND validate. Right now, leaving the user-control causes validation to fire twice.

+2  A: 

The best model for this sort of thing will be creating custom events on your user control, and raising them at the appropriate times.

Your scenario is fairly complex, but not unheard of. (I'm actually in a very similar mode on one of my current projects.) The way I approach it is that the user control is responsible for its own validation. I don't use CausesValidation; instead at the appropriate user control point, I perform validation through an override of ValidateChildren(). (This usually happens when the user clicks "Save" or "Next" on the user control, for me.)

Not being familiar with your user control UI, that may not be 100% the right approach for you. However, if you raise custom events (possibly with a custom EventArgs which specifies whether or not to perform validation), you should be able to get where you want to be.

John Rudy
+5  A: 
spoon16
Thanks, this is what I wound up doing, except instead of MouseLeave, I used FocusLeave, since potentially erroring every time the user moves his mouse could get irritating. Also, thanks for going through all the work for this!
Brock G
A: 

You will need to wire up the events you care about capturing inside your user control, and publish them through some custom event properties on the user control itself. A simple example would be wrapping a button click event:

// CustomControl.cs
// Assumes a Button 'myButton' has been added through the designer

// we need a delegate definition to type our event
public delegate void ButtonClickHandler(object sender, EventArgs e);

// declare the public event that other classes can subscribe to
public event ButtonClickHandler ButtonClickEvent;

// wire up the internal button click event to trigger our custom event
this.myButton.Click += new System.EventHandler(this.myButton_Click);
public void myButton_Click(object sender, EventArgs e)
{
  if (ButtonClickEvent != null)
  {
    ButtonClickEvent(sender, e);
  }
}

Then, in the Form that uses that control, you wire up the event like you would any other:

// CustomForm.cs
// Assumes a CustomControl 'myCustomControl' has been added through the desinger
this.myCustomControl.ButtonClickEvent += new System.EventHandler(this.myCustomControl_ButtonClickEvent);
myCustomControl_ButtonClickEvent(object sender, EventArgs e)
{
  // do something with the newly bubbled event
}
Goyuix
A: 

I would like to chime in that, as described, it actually sounds like you're chasing a red herring. While it seems like you have a situation where the lack of event bubbling in WinForms is causing you trouble, the reality is that a poor architecture is forcing you into needing event bubbling when you shouldn't.

If you can refactor/restructure your design such that the controls are working with a common data model (MVC/MVP are obvious choices) then you can simply apply common WinForms patterns like PropertyChanged events on the model to tell your main form and any other controls which consume that data to update themselves.

In short, the other answers are reasonable in that they answer the question as asked. But from a code quality standpoint, I think the better answer is to separate your data from the UI.

hemp