2011-07-20 43 views
4

私は、ユーザーコントロールを動的にロードする方法を(私に)実証するためのテストプロジェクトを構築しています。何かが起こったことを親に通知するためにコントロールの配線を除いてすべてが機能します。この問題は、ユーザーコントロールのイベントを親ページのイベントハンドラに接続しようとする行に問題があります。 "NotifyParentEvent"イベントは表示されず、コンパイラはそれを禁止します(イベントはSystem.Web.UI.Controlで定義されていません)。私は、コントロールの代わりにUserControlを使用しようとしましたが、無駄です。動的にロードされるユーザーコントロールのイベントへのバインド

Control control = Page.LoadControl(SavedControlVirtualPath); 
if (control != null) 
{ 
    control.ID = control.GetType().Name; 
>>>>> control.NotifyParentEvent += new EventHandler(UserControlNotificationHandler); 
    controlPlaceholder.Controls.Add(control); 
} 

ユーザーコントロールの背後にあるコード:

public partial class UserControls_WebUserControl1 : System.Web.UI.UserControl 
{ 
    public event CommandEventHandler NotifyParentEvent; 

    private void NotifyParent(string message) 
    { 
     if (NotifyParentEvent != null) 
     { 
      CommandEventArgs e = new CommandEventArgs("Control1 Action", message); 
      NotifyParentEvent(this, e); 
     } 
    } 
} 

親ページ:

public partial class _Default : System.Web.UI.Page 
{ 
    private string SavedControlVirtualPath 
    { 
     get {return (ViewState["savedControlPath"] == null || (string)ViewState["savedControlPath"] == string.Empty) 
       ? null : (string)ViewState["savedControlPath"]; } 
     set { ViewState["savedControlPath"] = value; } 
    } 

    private void ReloadControl() 
    { 
     controlPlaceholder.Controls.Clear(); 
     if (SavedControlVirtualPath != null) 
     { 
      Control control = Page.LoadControl(SavedControlVirtualPath); 
      if (control != null) 
      { 
       // Gives the control a unique ID. It is important to ensure 
       // the page working properly. Here we use control.GetType().Name 
       // as the ID. 
       control.ID = control.GetType().Name; 
       control.NotifyParentEvent += new EventHandler(UserControlNotificationHandler); <== THIS LINE WON'T COMPILE 
       controlPlaceholder.Controls.Add(control); 
      } 
     } 
    } 

    private void UserControlNotificationHandler(object sender, CommandEventArgs e) 
    { 
     // ??? 
    } 

    protected void Page_Init(object sender, EventArgs e) 
    { 
     lblLastEvent.Text += "Page_Init<br />"; 
     LoadUserControls(); 
    } 

    protected void Page_Load(object sender, EventArgs e) 
    { 
     lblLastEvent.Text += string.Format("{0} on main page<br />", (this.IsPostBack) ? "Postback" : "Page_Load"); 
     ReloadControl(); 
    } 

    protected void rblControlSelector_Changed(object sender, EventArgs e) 
    { 
     lblLastEvent.Text += "rblControlSelector_Changed<br />"; 
     LoadUserControls(); 
    } 

    private void LoadUserControls() 
    { 
     Label lbl = new Label(); 
     controlPlaceholder.Controls.Clear(); 
     switch (rblControlSelector.SelectedValue) 
     { 
      case "0": 
       lblLastEvent.Text = "Unload/Clear<br />"; 
       SavedControlVirtualPath = ""; 
       break; 

      case "1": 
       lblLastEvent.Text += "Adding control #1<br />"; 
       SavedControlVirtualPath = "~/UserControls/WebUserControl1.ascx"; 
       break; 

      case "2": 
       lblLastEvent.Text += "Adding control #2<br />"; 
       SavedControlVirtualPath = "~/UserControls/WebUserControl2.ascx"; 
       break; 

      case "3": 
       lblLastEvent.Text += "Adding control #3<br />"; 
       SavedControlVirtualPath = "~/UserControls/WebUserControl3.ascx"; 
       break; 

     } 
     if (!string.IsNullOrEmpty(SavedControlVirtualPath)) 
     { 
      ReloadControl(); 
     } 
    } 
} 
+0

があれば私に知らせて、下記の私の質問を編集しましたそれは役に立ちます –

答えて

4

オプション1

を使用していると仮定し

dynamic control = Page.LoadControl(SavedControlVirtualPath); 

別名

イベントハンドラを添付してください。基本的には、あなたのReloadControl方法では、このコード行を置き換える:

control.NotifyParentEvent += new EventHandler(UserControlNotificationHandler); 

次のように:より一般的なアプローチは、インターフェイスを作成することです

if(control is UserControls_WebUserControl1) 
{ 
    (control as UserControls_WebUserControl1).NotifyParentEvent += new EventHandler(UserControlNotificationHandler); 
} 

オプション2

とダイナミックコントロールがそのインターフェイスを実装しているかどうかを確認します。

インターフェースを作成します。

interface INotifyParent 
{ 
    event CommandEventHandler NotifyParentEvent; 
} 

は、インターフェイスを実装します。

public partial class UserControls_WebUserControl1 : System.Web.UI.UserControl, INotifyParent 
{ 
    public event CommandEventHandler NotifyParentEvent; 

    private void NotifyParent(string message) 
    { 
     if (NotifyParentEvent != null) 
     { 
      CommandEventArgs e = new CommandEventArgs("Control1 Action", message); 
      NotifyParentEvent(this, e); 
     } 
    } 
} 

チェックを動的制御がインタフェースを実装している場合:

if(control is INotifyParent) 
{ 
    (control as INotifyParent).NotifyParentEvent += new EventHandler(UserControlNotificationHandler); 
} 
+0

私はこれを試しますが、この解決方法では各コントロールのクラス名を知っている必要があります。 NotifyParentHandlerイベントで動的に決定される一般的なソリューションが必要です。定義されている場合は、それを接続します。 –

+0

イベントを公開するインターフェイスを作成し、コントロールにインターフェイスを実装させる必要があります。このようにして、具体的なコントロールタイプではなくインターフェイスタイプにキャストできます。また、イベントを実装する基本クラスを使用すると、各コントロールのコードを複製する必要がなくなります。 –

+0

VassiliとTim Stallの記事(http://www.4guysfromrolla.com/articles/110304-1.aspx)のおかげで、私はこれを働かせました。いくつかの調整が必要でしたが、もし誰かがソースコードを望むなら、私に知らせてください。 –

0

はあなたのEventHandlerを追加する前に、それに制御をキャストすることは適切な型です試してみてください。

これはうまくいかないのですが、コントロールではなくダイナミックタイプを使用してキャストしてみてください。このコードは、あなたがするためにあなたがNotifyParentEventイベントを実装する型に制御をキャストする必要があります.NET 4.0

+0

それが動的に読み込まれたコントロールであることを考えると、私はそれが適切な型であるかわかりません。あなたが考えているコードの例を教えてもらえますか?私はこれが私がまだ理解していない "反映"を必要とするかもしれないと思う。 –

関連する問題