2012-11-16 44 views
0

在我的窗体上,我有2个UserControls(ButtonDiscount,ButtonAdvertisment)继承了FadeControl。 FadeControl继承UserControl类,用于在淡出等控件上执行自定义内容。从另一个usercontrol访问usercontrol的方法

我的2个用户控件每个只有一个按钮,因此这两个缺乏想象力的名称。

单击其中一个usercontrols上的该按钮,我需要从另一个UserControl访问FadeControl中的方法。另一个按钮则相反。

我已经做了下面,就在用户控件ButtonDiscount事件点击:

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

它的工作原理就像一个魅力,但我不认为这是正确的做法,是有另一种方式从另一个UserControl的父类访问该方法?

我无法通过UserControl构造函数传递它,设计师每次都会发生故障。

+1

你不能只调用'buttonAdvertisment1.FadeOut(true);'? –

+0

@Mario号我从'ButtonDiscount'中看不到它。即使'FadeOut'是公开的。 –

+0

啊,这是UserControl ButtonDiscount中的代码...然后我看到了。然后使用事件,并在主窗体(用户控件按钮的容器)中将事件绑定到彼此的淡出方法。 –

回答

0

你有2个单独的用户控件,它们彼此不知道,这是好的,并保持你的代码松散耦合。现在你想要做的是让他们以某种方式了解对方并进行交流。让他们意识到彼此打破了松耦合,是一个糟糕的设计。

我会建议创建一个第三控件,它将两者连接在一起并处理它们之间的所有通信。您的每个原始控件都将具有公共事件,父控件可以对其进行订阅并进行适当处理。

更多信息检查调解模式:http://en.wikipedia.org/wiki/Mediator_pattern

+1

但是,他们是不是把它们放在一起并且应该处理沟通的形式?事情就是我想要做的事 - 从用户控制的事件做到另一方面。 –

+0

是的,把他们放在一起的形式也可以作为中间人。主要的一点是,这两个用户控件中的每一个都应该提供公共API,中间人将通过这些公共API来控制他们的行为和交流。这两个用户控件不应该直接相互通信。 – niaher

+0

好吧,我试图通过构造函数来做到这一点。但正如我所说,我发现有更多的人在网上说,设计师失败并开始行事滑稽。 –

0

你所做的是好的 - 你可以通过暴露当你点击这些控制按钮触发的事件,然后通过引用对方这样做(订阅那些,编写代码以淡化“this”控件)。

但是,这对于一个简单的解决方案可能有点太多了。

我会说你的解决方案是,如果你要改变控制的名称,那么它停止工作。你可以改为:

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

这样你就不再与控件名称绑定 - 但是控件的类型。你需要在你的代码文件中使用using System.Linq;才能工作。当然,这依赖于这样一个事实,即父代中只有另一个该控制类型的实例。

如果你有兴趣在我提到的第一个解决方案 - 那么这个代码段应有助于证明:

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 

一旦你有做过 - 在您的形式,假设你有_buttonAdvertisement_buttonDiscount成员的形成和后,他们正在初始化 - 你只需要做:

_buttonAdvertisement.AttachTo(_buttonDiscount); 

这将立即都控件绑定到对方。

注意 - 为了回应下面的评论 - 我已在FadeControl中为另一个FadeControl的事件处理程序Clicked保护和虚拟 - 因此您可以覆盖它。

+0

虽然使用'FirstOrDefault()'来查找按钮会起作用,但我看不出这是一种好的做法。例如,可能会添加更多ButtonAdvertisement。 –

+0

已经改变了我的答案,以更加防弹的解决方案。我不喜欢'OfType .FirstOrDefault()' - 所以建立了一个解决方案,可以用于更多场景,并且不依赖于搜索控件。这就是说 - 尽管这是一个简单的解决方案,但将两个控件组合在一个通用的逻辑父控件中非常简单,该控件实际上看起来并不具有视觉差异性,因此在实践中使搜索变得十分简单。 –

+0

如果对于不同的FadeControl,'other_Clicked'的逻辑需要不同,则此解决方案将不起作用。 – niaher

相关问题