Recipe 5.5. Communicating Between User Controls


Problem

You have multiple user controls on a page, and one of the user controls needs to send data to another as, for example, when one control takes its form or content from the user's action on another.

Solution

Create a custom event argument class to define the message to be sent, a source user control, a destination user control, and a web form that contains both user controls. (See Recipes 5.1 and 5.2 for detailed steps.)

In the custom event argument class that defines the message to be sent:

  1. Inherit from EventArgs.

  2. Add a message property to contain the message data.

In the source user control:

  1. Create a custom event.

  2. Raise the event when the required action is performed, such as when a user completes her entry for a form.

In the destination user control:

  1. Create an event handler to receive the event from the source user control.

  2. Display the message received.

In the web form used to test the user control communication:

  1. Add the source user control.

  2. Add the destination user control.

  3. "Wire" the event raised in the source user control to the event handler in the destination user control in the Page_Load event of the web form.

The output of a test page showing one user control communicating with another appears in Figure 5-4. The code for our example application that implements the solution is shown in Examples 5-15, 5-16, 5-17, 5-18, 5-19, 5-20, 5-21, 5-22, 5-23, 5-24 through 5-25. Examples 5-15 (VB) and 5-16 (C#) show the custom event argument class used to define the message sent. Example 5-17 shows the .ascx file for the source user control. Examples 5-18 and 5-19 show the VB and C# code-behind for the source user control. Example 5-20 shows the .ascx file for the destination user control. Examples 5-21 and 5-22 show the VB and C# code-behind for the destination user control. Example 5-23 shows the .aspx file for the web form used to demonstrate the user controls and their inter-connection. Examples 5-24 and 5-25 show the VB and C# code-behind for the demonstration web form.

Figure 5-4. Communicating between user controls output


Discussion

Rather than dwell on the basic content and creation of user controls, which is the subject of the previous recipes in the chapter, this recipe focuses on the interaction between user controls. The approach we advocate for handling this interaction involves creating a custom event for the source user control and raising the event when the communication is to be initiated, such as when the user clicks a button to complete his entry for the form. To receive the event from the source user control, the destination user control must have an event handler tailored for that purpose.

In our approach, creating the custom event for the source user control involves creating a custom event argument class, which provides the ability to add a message to the event arguments. It involves using a delegate, which is a convenient way to pass to the destination user control a reference to an event handler for the OnSend event raised by the source user control.

We've created an application to illustrate our approach. Because of the unusually high number of interrelated files, this example may appear overwhelming at first, but it is actually pretty straightforward. Keep in mind the four basic pieces:

  1. A custom event argument class defining the message sent

  2. A user control that sends a message (the source)

  3. A user control that receives the message (the destination)

  4. A web form that contains the two user controls and wires them together

The custom event argument class provides the ability to add the message to the event arguments. This class inherits from System.EventArgs and adds a message property as shown in Examples 5-15 (VB) and 5-16 (C#).

The source user control contains only a button used to initiate sending a message.

The source user control code-behind contains the bulk of the code. First, we define a new delegate signature, customMessageHandler, to allow the MessageEventArgs object to be passed as the event arguments. Without this delegate, you would have to use the EventArgs object, which does not provide the ability to pass custom information. An event is then defined with this type of delegate.

A delegate is a class that can hold a reference to a method. A delegate class has a signature and it can hold references only to methods that match its signature. The delegate object is passed to code that calls the referenced method without having to know at compile time which method will be invoked. The most common example is building a generic sort routine, one that allows you to sort any type of data, where you pass to it the data to be sorted and a reference to the comparison routine needed to compare the particular data. The situation here is somewhat similar. In this case, we are passing a message to the destination user control (contained within an instance of MessageEventArgs) and a reference to an event handler for the OnSend event raised by the source user control. A delegate provides the best, most convenient way to accomplish this.


Our remaining task in the source user control code-behind is to provide a standard event handler for the send message button click event. In this handler, an instance of MessageEventArgs is created and populated with the message being sent. The OnSend event is then raised, passing a reference to the source user control as the event source and a reference to the messageArgs object containing the message being sent. In our example, this is a hardwired message, but it demonstrates the basic principal.

In C#, the OnSend event must be checked to make sure it is not null before raising the event. Failure to do so will result in an exception being thrown if no handler is wired to the event. This is not required for VB.


Our example's destination user control, which is shown in Example 5-20, contains only a label used to display the message sent from the source user control.

The destination user control code-behind, shown in VB in Example 5-21 and in C# in Example 5-22, contains a single method to handle the event raised from the source user control. The signature of the method must match the customMessageHandler delegate defined in the source user control. The only operation performed is to update the label in the user control with the message passed in the event arguments.

In our example, the .aspx file for the web form used to demonstrate the user controls, which appears in Example 5-23, includes the registration of the two user controls and the tags within the HTML where the user controls are to be displayed.

The code-behind for the demonstration web form, shown in VB in Example 5-24 and in C# in Example 5-25, provides the glue for tying the event from the source user control to the destination user control. This is done by adding the updateLabel of the destination user control as an event handler for the OnSend event raised by the source user control. We are adding a delegate to the source user control's OnSend event's event handler list; that list now consists of just one event handler but can include more.

Event delegates in .NET are multicast, which allows them to hold references to more than one event handler. This provides the ability for one event to be processed by multiple event handlers. You can try it yourself by adding a label to the demonstration web form, adding a new event handler in the web form, and then adding your new event handler to the OnSend event's event handler list. This will cause the label on the destination user control and the web form to be updated with the message from the source user control. An example that does this with multiple user controls is shown in Recipe 5.5.


In VB, when using the event/delegate model, the keyword WithEvents is not used. (The WithEvents keyword indicates that a declared object variable refers to a class instance that can raise events.) WithEvents and the event/delegate model can be intermixed, but they should not be used for the same event.


See Also

Recipe 5.5 and Programming C# or Programming Visual Basic .NET (O'Reilly), both by Jesse Liberty, for more about delegates

Example 5-15. Class defining message passed between user controls (.vb)

 Option Explicit On Option Strict On Imports System Namespace ASPNetCookbook.VBExamples   ''' <summary>   ''' This class class provides the definition of the custom event arguments   ''' used as the event arguments for the message sent from this control   ''' This class simply inherits from System.EventArgs and adds a message   ''' property   ''' </summary>   Public Class MessageEventArgs     Inherits EventArgs Private mMessage As String '''*********************************************************************** ''' <summary> ''' This property provides the ability to get/set the message in the ''' event args ''' </summary> Public Property message( ) As String   Get     Return (mMessage)   End Get   Set(ByVal Value As String)     mMessage = Value   End Set     End Property   End Class 'MessageEventArgs End Namespace 

Example 5-16. Class defining message passed between user controls (.cs)

 using System; namespace ASPNetCookbook.CSExamples {   /// <summary>   /// This class provides the definition of the custom event arguments used   /// as the event arguments for the message sent from this control. This   /// class simply inherits from System.EventArgs and adds a message property.   /// </summary>   public class MessageEventArgs   {     private String mMessage; /// <summary> /// This property provides the ability to get/set the message in the /// event args /// </summary> public String message {   get   { return (mMessage);   }   set   {     mMessage = value;   } } // message   } // MessageEventArgs } 

Example 5-17. Communicating between controlssource user control (.ascx)

 <%@ Control Language="VB" AutoEventWireup="false"      CodeFile="CH05UserControlCommSourceVB.ascx.vb"  Inherits="ASPNetCookbook.VBExamples.CH05UserControlCommSourceVB" %> <asp:Button  runat="server"    Text="Send Message"    OnClick="btnSendMessage_Click" /> 

Example 5-18. Communicating between controlssource user control (.vb)

 Option Explicit On Option Strict On Imports System.Drawing Namespace ASPNetCookbook.VBExamples   ''' <summary>   ''' This class provides the code-behind for   ''' CH05UserControlCommSourceVB.ascx   ''' </summary>   Partial Class CH05UserControlCommSourceVB     Inherits System.Web.UI.UserControl 'define the delegate handler signature and the event that will be raised 'to send the message Public Delegate Sub customMessageHandler(ByVal sender As System.Object, _  ByVal e As MessageEventArgs) Public Event OnSend As customMessageHandler '''*********************************************************************** ''' <summary> ''' This routine provides the event handler for the send message button ''' click event. It creates a new MessageEventArgs object then raises ''' an OnSend event ''' </summary> ''' ''' <param name="sender">Set to the sender of the event</param> ''' <param name="e">Set to the event arguments</param> Protected Sub btnSendMessage_Click(ByVal sender As Object, _    ByVal e As System.EventArgs)   Dim messageArgs As New MessageEventArgs   messageArgs.message = "This message came from the source user control"   RaiseEvent OnSend(Me, messageArgs)       End Sub 'btnSendMessage_Click    End Class 'CH05UserControlCommSourceVB End Namespace 

Example 5-19. Communicating between controlssource user control (.cs)

 using System; namespace ASPNetCookbook.CSExamples {     /// <summary> /// This class provides the code-behind for /// CH05UserControlCommSourceCS.ascx /// </summary> public partial class CH05UserControlCommSourceCS : System.Web.UI.UserControl {   // define the delegate handler signature and the event that will be raised   // to send the message   public delegate void customMessageHandler(Object sender, MessageEventArgs e);   public event customMessageHandler OnSend;   ///***********************************************************************   /// <summary>   /// This routine provides the event handler for the send message button   /// click event. It creates a new MessageEventArgs object then raises   /// an OnSend event   /// </summary>   ///   /// <param name="sender">Set to the sender of the event</param>   /// <param name="e">Set to the event arguments</param>   protected void btnSendMessage_Click(object sender, EventArgs e)   {     MessageEventArgs messageArgs = new MessageEventArgs(); messageArgs.message = "This message came from the source user control"; if (OnSend != null) {   OnSend(this, messageArgs); }  }  // btnSendMessage_Click    }  // CH05UserControlCommSourceCS } 

Example 5-20. Communicating between controlsdestination user control (.ascx)

 <%@ Control Language="VB" AutoEventWireup="false"  CodeFile="CH05UserControlCommDestinationVB.ascx.vb"  Inherits="ASPNetCookbook.VBExamples.CH05UserControlCommDestinationVB" %> x<asp:Label  Runat="server">No Message Yet</asp:Label> 

Example 5-21. Communicating between controlsdestination user control (.vb)

 Option Explicit On Option Strict On Imports System Namespace ASPNetCookbook.VBExamples ''' <summary> ''' This class provides the code behind for ''' CH05UserControlCommDestinationVB.ascx ''' </summary> Partial Class CH05UserControlCommDestinationVB Inherits System.Web.UI.UserControl '''*********************************************************************** ''' <summary> ''' This routine provides the event handler that is the recipient of the ''' event raised by the source user control. ''' </summary> ''' ''' <param name="sender">Set to the sender of the event</param> ''' <param name="e">Set to the event arguments</param> Public Sub updateLabel(ByVal sender As System.Object, _   ByVal e As MessageEventArgs) 'update the label with the message in the event arguments labMessage.Text = e.message End Sub 'updateLabel  End Class 'CH05UserControlCommDestinationVB End Namespace 

Example 5-22. *Communicating between controlsdestination user control (.cs)

 using System; namespace ASPNetCookbook.CSExamples {   /// <summary>   /// This class provides the code behind for   /// CH05UserControlCommDestinationCS.ascx   /// </summary>   public partial class CH05UserControlCommDestinationCS :     System.Web.UI.UserControl   {     ///*********************************************************************** /// <summary> /// This routine provides the event handler that is the recipient of the /// event raised by the source user control. /// </summary> /// /// <param name="sender">Set to the sender of the event</param> /// <param name="e">Set to the event arguments</param> public void updateLabel(Object sender, MessageEventArgs e) { // update the label with the message in the event arguments labMessage.Text = e.message; } // updateLabel   } // CH05UserControlCommDestinationCS } 

Example 5-23. Communicating between controlsmain form (.aspx)

 <%@ Page Language="VB" MasterPageFile="~/ASPNetCookbookVB.master";  AutoEventWireup="false"  CodeFile="CH05UserControlCommTestVB.aspx.vb"  Inherits="ASPNetCookbook.VBExamples.CH05UserControlCommTestVB"  Title="User Control Communication Test" %> <%@ Register TagPrefix="ASPCookbook" TagName="SourceControl" src="/books/1/505/1/html/2/CH05UserControlCommSourceVB.ascx" %> <%@ Register TagPrefix="ASPCookbook" TagName="DestinationControl" src="/books/1/505/1/html/2/CH05UserControlCommDestinationVB.ascx" %> <asp:Content  Runat="server" ContentPlaceHolder>   <div align="center" >        User Control Communication Test (VB)       </div>   <table width="60%" align="center" border="0">       <tr> <td >   Source User Control: </td>   </tr>   <tr>  <td bgcolor="#ffffcc" align="center" height="75">      <ASPCookbook:SourceControl  runat="server" />  </td>   </tr>   <tr>  <td>&nbsp;</td>   </tr>   <tr> <td >   Destination User Control: </td>   </tr> <tr> <td bgcolor=";#ffffcc" align="center" height="75">       <ASPCookbook:DestinationControl  runat="server" /> </td> </tr>   </table> </asp:Content> 

Example 5-24. Communicating between controlsmain form (.vb)

 Option Explicit On Option Strict On Imports System.Drawing Namespace ASPNetCookbook.VBExamples   ''' <summary>   ''' This class provides the code behind for   ''' CH05UserControlCommTestVB.aspx   ''' </summary>   Partial Class CH05UserControlCommTestVB     Inherits System.Web.UI.Page '''*********************************************************************** ''' <summary> ''' This routine provides the event handler for the page load event. It ''' is responsible for initializing the controls on the page. ''' </summary> ''' ''' <param name="sender">Set to the sender of the event</param> ''' <param name="e">Set to the event arguments</param> Protected Sub Page_Load(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Me.Load   'wire the event to the destination user control handler   AddHandler ucSource.OnSend, AddressOf ucDestination.updateLabel End Sub 'Page_Load   End Class 'CH05UserControlCommTestVB End Namespace 

Example 5-25. Communicating between controlsmain form (.cs)

 using System; namespace ASPNetCookbook.CSExamples {   /// <summary>   /// This class provides the code behind for   /// CH05UserControlCommTestCS.aspx   /// </summary>   public partial class CH05UserControlCommTestCS : System.Web.UI.Page   { ///*********************************************************************** /// <summary> /// This routine provides the event handler for the page load event. /// It is responsible for initializing the controls on the page. /// </summary> /// /// <param name="sender">Set to the sender of the event</param> /// <param name="e">Set to the event arguments</param> protected void Page_Load(object sender, EventArgs e) {   // wire the event to the destination user control handler ucSource.OnSend +=   new CH05UserControlCommSourceCS.customMessageHandler(ucDestination.updateLabel); } // Page_Load   } // CH05UserControlCommTestCS } 



ASP. NET Cookbook
ASP.Net 2.0 Cookbook (Cookbooks (OReilly))
ISBN: 0596100647
EAN: 2147483647
Year: 2003
Pages: 202

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net