2012-07-21 41 views
1

我有兩個名爲UCCreateProfile.ascx(用於創建/編輯個人檔案數據)和UCProfileList.ascx(用於在GridView中顯示個人檔案數據)的用戶控件。現在每當創建一個新的配置文件時,我想更新我的UCProfileList控件以顯示新條目。如何實現觀察者模式以在asp.net中使用用戶控件

針對上述問題的最佳解決方案我必須去觀察者模式。在我的情況下,UCCreatedProfile是一個Subject/Observable,UCProfileList是Observer,根據模式定義,當觀察者初始化時,它知道誰是我的Subject/Observable,並將它自己添加到Subject/Observable列表中。因此,無論何時在Subject/Observable發生變化,它都會被通知。

這種模式最符合我的要求,但我得到很少的問題來實現這個描述如下。

我正在CMS(Umbraco)下工作,我沒有任何物理容器頁面(.aspx)。我要做的是使用以下代碼在UCProfileList(Observer)onLoad事件中查找UCCreateProfile(Subject/Observable)。

private Control FindCreateProfileControl() 
{ 
    Control control = null; 
    Control frm = GetFormInstance(); 
    control = GetControlRecursive(frm.Controls); 

     return control; 
} 

其中GetFormInstance()方法是

private Control GetFormInstance() 
    { 
     Control ctrl = this.Parent; 
     while (true) 
     { 
      ctrl = ctrl.Parent; 
      if (ctrl is HtmlForm) 
      { 
       break; 
      } 
     } 
     return ctrl; 
    } 

和GetControlRecursive()方法是

private Control GetControlRecursive(ControlCollection ctrls) 
    { 
     Control result = null; 
     foreach (Control item in ctrls) 
     { 
      if (result != null) break; 
      if (item is UCCreateProfile) 
      { 
       result = item; 
       return result; 
      } 
      if (item.Controls != null) 
       result = GetControlRecursive(item.Controls); 
     } 
     return result; 
    } 

這樣我可以找到UCCreateProfile(題目/可觀察的)用戶中UCProfileList控制( Observer),但找出(Subject/Observable)的方式並不是那麼快。正如你所看到的,我需要遍歷所有的控件,首先找到HtmlForm控件,然後循環HtmlForm控件下的所有子控件,並找到我們正在尋找的適當的控件。其次,如果非常重要,我的代碼只能在UCCreatedProfile.ascx(Subject/Observable)放置在UCProfileList.ascx(Observer)之前,因爲這種方式UCCreateProfile將首先加載並在UCProfileList中查找時,將用戶控件放置在容器中。但是如果有人改變這兩個控件的位置,我的代碼將無法工作。

因此,爲了擺脫這些問題,我需要一些解決方案,它可以更快地工作,並且獨立於控件的位置。

我已經想出了一些解決方案,如下所述。請讓我知道這是否是一個好方法。如果有其他選擇,請告訴我。

我有一個會話級別的變量(字典Dictionary<ISubject, List<Observer>>)。無論哪個用戶控件首先被初始化/加載,用戶控件都會將其自身添加到此字典中。
如果首先添加Subject/Observable,則會在此字典中找到相應的觀察者。
如果首先添加Observer,它將添加到帶有空條目的字典中。當主題添加時,關聯被創建。

問候,

/RIZWAN

+0

看起來就像你有一個與字典會話對象的好解決方案!你有什麼理由尋找替代品嗎? – TheSilverBullet 2012-09-04 13:31:00

回答

2

Observer模式最好是在.NET通過事件和委託實施。如果你使用事件和代表,你提到的Dictionary變得完全沒有必要。例如,見下面這段代碼(僅顯示重要的部分):

public partial class UserProfile : System.Web.UI.UserControl 
{ 
    //This is the event handler for when a user is updated on the UserProfile Control 
    public event EventHandler<UserUpdatedEventArgs> UserUpdated; 

    protected void btnUpdate_Click(object sender, EventArgs e) 
    { 
     //Do whatever you need above and then see who's subscribed to this event 
     var userUpdated = UserUpdated; 
     if (userUpdated != null) 
     { 
      //Initialize UserUpdatedEventArgs as you want. You can, for example, 
      //pass a "User" object if you have one 
      userUpdated(this,new UserUpdatedEventArgs({....})); 
     } 
    } 
} 

public class UserUpdatedEventArgs : EventArgs 
{ 
    public User UserUpdated {get;set;} 
    public UserUpdatedEventArgs (User u) 
    { 
     UserUpdated=u; 
    } 
} 

現在訂閱從上UserListControlUserProfile控制UserUpdated事件,因爲這很容易:

public partial class UserList : System.Web.UI.UserControl 
{ 
    protected void Page_Load(object sender, EventArgs e) 
    { 
     //Find the UserProfile control in the page. It seems that you already have a 
     //recursive function that finds it. I wouldn't do that but that's for another topic... 
     UserProfile up = this.Parent.FindControl("UserProfile1") as UserProfile; 
     if(up!=null) 
      //Register for the event 
      up.UserUpdated += new EventHandler<UserUpdatedEventArgs>(up_UserUpdated); 
    } 

    //This will be called automatically every time a user is updated on the UserProfile control 
    protected void up_UserUpdated(object sender, UserUpdatedEventArgs e) 
    { 
     User u = e.UserUpdated; 
     //Do something with u... 
    } 
}