简体   繁体   English

用户控件从另一个用户控件的访问方法

[英]Access method of an usercontrol from another usercontrol

On my form I have 2 UserControls (ButtonDiscount, ButtonAdvertisment) that inherit FadeControl. 在我的表单上,我有2个继承FadeControl的UserControls(ButtonDiscount,ButtonAdvertisment)。 FadeControl inherits UserControl class and is used to do custom stuff on the controls like fade out. FadeControl继承UserControl类,用于对控件进行自定义操作,例如淡出。

My 2 UserControls each have just one button hence those two unimaginative names. 我的2个UserControl都只有一个按钮,因此只有两个按钮。

On click of that button on one of usercontrols, I need to access the method in FadeControl from the other UserControl. 在一个用户控件上单击该按钮时,我需要从另一个用户控件访问FadeControl中的方法。 The other button does the opposite. 另一个按钮则相反。

I've done the following, on the event click in the UserControl ButtonDiscount: 我完成了以下操作,在事件中,单击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? 它像一种魅力一样工作,但是我认为这不是正确的方法,是否还有另一种方法可以从另一个UserControl的父类访问该方法?

I can't pass it thru a UserControl constructor, the designer breaks down every time. 我无法通过UserControl构造函数传递它,设计器每次都会崩溃。

You have 2 separate user controls which are not aware of each other, which is good and keeps your code loosely-coupled. 您有2个彼此不认识的单独的用户控件,这很不错,并且可以使您的代码保持松散耦合。 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 检查介体模式以获取更多信息: http : //en.wikipedia.org/wiki/Mediator_pattern

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). 您所做的一切很好-您可以通过以下方式来实现:暴露那些单击这些控件中的按钮时触发的事件,然后相互传递引用(订阅这些控件,编写代码以淡化“ this”控件)。

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; 您将需要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_buttonDiscount成员,并且它们初始化之后-您只需执行以下操作:

_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. 注意-为了响应下面的评论-我在FadeControl为另一个FadeControl的Clicked事件设置了事件处理程序, FadeControl受到保护和虚拟化-因此您可以覆盖它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM