2012-11-16 40 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

相關問題