niksa.lovrinic
niksa.lovrinic

Reputation: 3

Access method of an usercontrol from another usercontrol

On my form I have 2 UserControls (ButtonDiscount, ButtonAdvertisment) that inherit FadeControl. FadeControl inherits UserControl class and is used to do custom stuff on the controls like fade out.

My 2 UserControls each have just one button hence those two unimaginative names.

On click of that button on one of usercontrols, I need to access the method in FadeControl from the other UserControl. The other button does the opposite.

I've done the following, on the event click in the UserControl ButtonDiscount:

private void button1_Click(object sender, EventArgs e)
{
    ButtonAdvertisment ba = (ButtonAdvertisment)this.Parent.Controls.Find("buttonAdvertisment1", true)[0];
    ba.FadeOut(true);
}

It works like a charm, but I don't think this is the right way, is there another way to access the method from the parent class of the other UserControl?

I can't pass it thru a UserControl constructor, the designer breaks down every time.

Upvotes: 0

Views: 1631

Answers (2)

Andras Zoltan
Andras Zoltan

Reputation: 42363

What you've done is fine - you could do it by exposing events that fired when you click the button in those controls, and then passing references to each other (subscribing to those, writing the code to fade 'this' control).

That might be a bit too much work for a simple solution, however.

What I would say about your solution is that if you were to change the name of control(s) then it stops working. You could instead do:

var ba = this.Parent.Controls.OfType<ButtonAdvertisement>().FirstOrDefault();

That way you're no longer tied to the control name - but the type of the control. You'll need a using System.Linq; in your code file for this to work. Of course, this relies on the fact that there is only ever one other instance of that control type in the parent.

If you're interested in the first solution I mentioned - then this code snippet should help demonstrate:

public class FadeControl {
  public event EventHandler Clicked;

  public void FadeOut(bool b){

  }

  public void AttachTo(FadeControl other){
    //splitting this operation to a public and private allows us to 
    //initiate an attach publicly, but then recurse privately without 
    //causing a stack overflow
    AttachToInternal(other);
    other.AttachToInternal(this);
  }

  private void AttachToInternal(FadeControl other){
    other.Clicked += Attached_Clicked;
  }

  protected virtual void Attached_Clicked(object sender, EventArgs e)
  {
    //fade me out
    FadeOut(true);
  }

  // provides a way for the deriving class to raise the Clicked event
  protected void OnButtonClicked(){
    if(Clicked != null) Clicked(this, null);
  }
}

public class ButtonDiscount : FadeControl {
  Button _button;

  //omitted: designer code

  //this is your handler for the _button clicked event 

  private void _button_Clicked(object sender, EventArgs e){
    //call the base class' OnButtonClicked method - to raise the event
    OnButtonClicked();
    //TODO: do work.
  }
}

//omitted - code for the ButtonAdvertisement class

Once you have that done - in your form, assuming you have _buttonAdvertisement and _buttonDiscount members in your form and after they're initialised - you simply do:

_buttonAdvertisement.AttachTo(_buttonDiscount);

And that will immediately bind both controls to each other.

Note - in response to a comment below - I've made the event handler in FadeControl for another FadeControl's Clicked event protected and virtual - so you can override it.

Upvotes: 0

g45rg34d
g45rg34d

Reputation: 9660

You have 2 separate user controls which are not aware of each other, which is good and keeps your code loosely-coupled. Now what you are trying to do is to make them somehow know about each other and communicate. Making them aware of each other breaks the loose-coupling and is a bad design.

What I would suggest is creating a 3rd control which will hold the two together and will handle all the communication between them. Each of your original controls will have public events, to which the parent control can subscribe and handle appropriately.

Check mediator pattern for more info: http://en.wikipedia.org/wiki/Mediator_pattern

Upvotes: 0

Related Questions