July 13, 2013

User Control自訂事件處理機制

現有需求如下

有一會員註冊頁面,使用者填寫完會員資料後按下註冊按鈕後顯示註冊結果在頁面上

我們將註冊表單設計成一個使用者控制項,而顯示訊息則設計成另一個使用者控制項,如此註冊表單和顯示訊息兩項功能都可以在其它地方reuse。

顯示訊息的功能很簡單,我們在ascx裡佈置一個Label控制項,在code-behind中則新增一個顯示訊息的方法
<asp:Label ID="Label_Message" runat="server"></asp:Label>

public void Show(string message)
{
    this.Label_Message.Text = message;
}

註冊表單的功能則簡單的佈置如下
<p>
    Email:
    <asp:TextBox ID="TextBox_Email" runat="server"></asp:TextBox>
</p>
<p>
    Name:
    <asp:TextBox ID="TextBox_Name" runat="server"></asp:TextBox>
</p>
<asp:Button ID="Button_Register" runat="server" OnClick="Button_Register_Click" Text="Register" />


protected void Button_Register_Click(object sender, EventArgs e)
{
    Alert alert = ((Alert)Page.FindControl("Alert1"));
    alert.Show(string.Format("User account {0} registered successfully",
        this.TextBox_Email.Text));
}

在按下Register按鈕後就會觸發Button_Register_Click事件,在上面我們先假設註冊成功,要顯示註冊成功的訊息。由於顯示訊息的控制項和註冊表單的控制項放在同一個Web Form中,所以先透過Page.FindControl找到顯示訊息的User Control接著呼叫其Show方法來顯示訊息


到這裡需求所描述的功能已大致完成。先不論資料驗證和顯示上安全性的疑慮,這樣的設計會有個問題,就是註冊表單控制項相依於顯示訊息控制項,以致無法獨立重複使用,而必須同時出現在頁面上,例如之後因應新需求要設計另一種顯示訊息的控制項時,就可能需要修改註冊表單的程式碼。

要解決上述使用者控制項相依的問題,可以在註冊表單控制項改以加入事件處理機制,並讓Web Form頁面訂閱註冊表單控制項的註冊完成事件,接著委派顯示訊息控制項來顯示註冊結果。
public partial class Registration : System.Web.UI.UserControl
{
    public event EventHandler<RegistrationEventArgs> OnRegistered;

    protected void Button_Register_Click(object sender, EventArgs e)
    {
        if (OnRegistered != null)
        {
            string message = string.Format("User account {0} registered successfully",
    this.TextBox_Email.Text);
            RegistrationEventArgs registrationEventArgs = new RegistrationEventArgs(message);
            OnRegistered(this, registrationEventArgs);
        }
    }
}

public class RegistrationEventArgs : EventArgs
{
    private string _message;

    public RegistrationEventArgs(string message)
    {
        this._message = message;
    }

    public string Message
    {
        get
        {
            return this._message;
        }
    }
}

在註冊表單控制項宣告了一個事件處理常式OnRegistered,並透過RegistrationEventArgs將註冊結果訊息傳遞出去,讓事件的訂閱者可以取得註冊結果訊息。
public partial class Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        this.Registration1.OnRegistered += (ucSender, ucEventArgs) =>
        {
            this.Alert1.Show(ucEventArgs.Message);
        };
    }
}

在Web Form頁面則是訂閱OnRegistered事件並於事件觸發時委派顯示訊息控制項顯示註冊結果。經由這種事件驅動的設計方式,使得註冊表單控制項可以獨立被重複使用而不相依顯示訊息控制項,往後若有不同類型的顯示訊息控制項,也僅須訂閱OnRegistered事件委派新的顯示訊息控制項即可。

No comments: