Composition vs. Rendering
While it is relatively easy to author a composite control, composition has a performance overhead because it has to create child controls. If you want optimal performance for your control, you can implement the rendering logic yourself by overriding the Render method. Additionally, you must implement any postback data processing and postback event handling needed by your control.
The following sample shows the control Rendered
, which renders a user interface that is equivalent to that provided in the Composite Server Control Sample. Rendered
does not use composition and hence is more complex to author.
The following members in Rendered
are identical to those in the Composite Server Control Sample.
- The public
Text
property. (However, in this case the property is not delegated to a child control.) - The public
Number
property. - The private
Sum
property. - The custom
Check
event.
Because Rendered
does not have child controls, it has to do the following additional work.
- Provide its own implementation for the text boxes.
- Provide its own implementation for a submit button.
- Implement IPostBackEventHandler.
- Implement IPostBackDataHandler.
- Override the Render method.
Note that Rendered
does not use ViewState to persist properties across round trips because state restoration is not needed in this scenario. Note also that in this sample the Render method writes raw HTML to the Write method of HtmlTextWriter. For an example of using the utility methods of HtmlTextWriter for rendering, see Rendering Server Controls Samples.
To build the sample, see the instructions in Server Control Samples.
using System;
using System.Web;
using System.Web.UI;
using System.Collections.Specialized;
namespace CustomControls
{
public class Rendered : Control, IPostBackDataHandler, IPostBackEventHandler
{
private String text1;
private String text2;
private String text = "Press the button to see if you won.";
private int number = 100;
private int Sum
{
get
{
return Int32.Parse(text1) +
Int32.Parse(text2);
}
}
public int Number
{
get
{
return number;
}
set
{
number = value;
}
}
public String Text {
get {
return text;
}
set {
text = value;
}
}
public event CheckEventHandler Check;
protected virtual void OnCheck(CheckEventArgs ce)
{
if (Check != null)
{
Check(this,ce);
}
}
public virtual bool LoadPostData(string postDataKey,
NameValueCollection values) {
text1 = values[UniqueID + "t1"];
text2 = values[UniqueID+ "t2"];
Page.RegisterRequiresRaiseEvent(this);
return false;
}
public virtual void RaisePostDataChangedEvent() {
}
public void RaisePostBackEvent(string eventArgument){
OnCheck(new CheckEventArgs(Sum - Number));
}
protected override void Render(HtmlTextWriter output) {
output.Write ("<h3>Enter a number : ");
output.Write("<INPUT type= text name = " + this.UniqueID + "t1" +
" value = '0' >");
output.Write("</h3><br>");
output.Write ("<br><h3>Enter another number : ");
output.Write("<INPUT type= text name = " + this.UniqueID + "t2" +
" value = '0' >");
output.Write("</h3><br>");
output.Write("<br><br><input type= submit name = " +
this.UniqueID + " value= 'Submit'>");
output.Write("<br><br><span style='height:50px;width:500px;'>"
+ Text + "</span>");
}
}
}
// CheckEvent.cs.
// Contains the code for the custom event data class CheckEventArgs.
// Also defines the event handler for the Check event.
using System;
namespace CustomControls
{
public class CheckEventArgs : EventArgs
{
private bool match = false;
public CheckEventArgs (int difference)
{
if (difference == 0)
{
match = true;
}
}
public bool Match
{
get
{
return match;
}
}
}
public delegate void CheckEventHandler(object sender, CheckEventArgs ce);
}
[Visual Basic]
Option Explicit
Option Strict
Imports System
Imports System.Web
Imports System.Web.UI
Imports System.Collections.Specialized
Namespace CustomControls
Public Class Rendered
Inherits Control
Implements IPostBackDataHandler, IPostBackEventHandler
Private text1 As String
Private text2 As String
Private _text As String = "Press enter to see if you won."
Private _number As Integer = 100
Private ReadOnly Property Sum() As Integer
Get
Return Int32.Parse(text1) + Int32.Parse(text2)
End Get
End Property
Public Property Number() As Integer
Get
Return _number
End Get
Set
_number = value
End Set
End Property
Public Property Text() As String
Get
Return _text
End Get
Set
_text = value
End Set
End Property
Public Event Check As CheckEventHandler
Protected Overridable Sub OnCheck(ce As CheckEventArgs)
RaiseEvent Check(Me, ce)
End Sub
Public Overridable Function LoadPostData(postDataKey As String, values As NameValueCollection) As Boolean Implements IPostBackDataHandler.LoadPostData
text1 = values(UniqueID & "t1")
text2 = values(UniqueID & "t2")
Page.RegisterRequiresRaiseEvent(Me)
Return False
End Function
Public Overridable Sub RaisePostDataChangedEvent() Implements IPostBackDataHandler.RaisePostDataChangedEvent
End Sub
Public Sub RaisePostBackEvent(eventArgument As String) Implements IPostBackEventHandler.RaisePostBackEvent
OnCheck(New CheckEventArgs(Sum - Number))
End Sub
Protected Overrides Sub Render(output As HtmlTextWriter)
output.Write("<h3>Enter a number : ")
output.Write("<INPUT type= text name = " & _
Me.UniqueID & "t1" & _
" value = '0' >")
output.Write("</h3><br>")
output.Write("<br><h3>Enter another number : ")
output.Write("<INPUT type= text name = " & _
Me.UniqueID & "t2" & _
" value = '0' >")
output.Write("</h3><br>")
output.Write("<br><br><input type= submit name = " & _
Me.UniqueID & _
" value= 'Submit'>")
output.Write("<br><br><span style='height:50px;width:500px;'>" & _
Text & "</span>")
End Sub
End Class
End Namespace
' CheckEvent.vb
' Contains the code for the custom event data class CheckEventArgs.
' Also defines the event handler for the Check event.
Imports System
Namespace CustomControls
Public Class CheckEventArgs
Inherits EventArgs
Private _match As Boolean = False
Public Sub New(difference As Integer)
If difference = 0 Then
_match = True
End If
End Sub
Public ReadOnly Property Match() As Boolean
Get
Return _match
End Get
End Property
End Class
Public Delegate Sub CheckEventHandler(sender As Object, ce As CheckEventArgs)
End Namespace
Using the Rendered Control on a Page
The following page uses the custom control Rendered
, defined in the preceding sample. Note that this page is identical to the page in Composite Server Control Sample, which uses a composite control instead of a rendered control.
<%@ Register TagPrefix="Custom" Namespace="CustomControls" Assembly = "CustomControls" %>
<script language="VB" runat=server>
Private Sub Sum_Checked(sender As Object, e As CheckEventArgs)
If e.Match = True Then
Rendered.Text = "<h2> You won a million dollars!!!! </h2>"
Else
Rendered.Text = "Sorry, try again. The numbers you entered don't add up to" & _
" the hidden number."
End If
End Sub
</script>
<html>
<body>
<h1> The Mystery Sum Game </h1><br>
<form runat=server>
<Custom:Rendered id = "Rendered" OnCheck = "Sum_Checked" Number= "10" runat = server/>
</form>
</body>
</html>