chapter 2: part 1 ( custom controls)
The word “render” has a special meaning in the context of server control development, which is different from the common meaning of the word where rendering refers to the Web browser’s task of displaying or rendering the HTMLmarkup that the browser receives from the server. Rendering in the context of server control development means generating the HTMLmarkup text that the server sends to the browser. In other words, server controls render (generate) the HTMLmarkup text that browsers render (display).
At runtime, the containing page creates an instance of a class named HtmlTextWriter and passes the instance into the Render methods of the server controls that the page contains. The HtmlTextWriter class exposes a method named write that these server controls can use to write out their HTMLmarkup text.
Adding Design-Time Attributes to Your Custom Controls
Property level attributes
[BrowsableAttribute(true)]
[DescriptionAttribute(“Gets and sets the payment method”)]
[DefaultValueAttribute(“Payment Method”)]
[CategoryAttribute(“Appearance”)]
public virtual string PaymentMethodText
{
get { return this.paymentMethodText; }
set { this.paymentMethodText = value; }
}
This code takes the following actions:
1. Annotates the PaymentMethodText property with the BrowsableAttribute(true) attribute to instruct the property browser to display the name and value of this property. By default, every public property is considered browsable. You should use this attribute on read-only properties to tell the property browser not to display them because there is no point in displaying a property if page developers can’t change its value.
2. Annotates the property with the DescriptionAttribute(“Gets and sets the payment method”) attribute to instruct the property browser to display the text “Gets and sets the payment method” every time the page developer selects the property.
3. Annotates the property with the DefaultValueAttribute(“Payment Method”) attribute to instruct the property browser to display the text “Payment Method” as the default value of the property.
4. Annotates the property with the CategoryAttribute(“Appearance”) attribute to instruct the property browser to display this property under the Appearance category.
Class level Attributes
When page developers select a server control in Visual Studio, they expect to see a particular property
of the control highlighted. This property is known as the default property of the server control. The following code annotates the CreditCardForm2 custom control with the DefaultPropertyAttribute(“CardholderNameText”) to mark the CardholderNameText property as the default property:
DefaultPropertyAttribute(“CardholderNameText”)]
public class CreditCardForm2 : Control
The following code annotates the CreditCardForm2 custom control with the class-level attribute ToolboxDataAttribute to specify default values for the properties of the CreditCardForm2 control:
[ToolboxData(“<{0}:CreditCardForm2 PaymentMethodText=’Payment Options’ CreditCardNoText=’Credit Card Number’ CardholderNameText=’Cardholder Full Name’
SubmitButtonText = ‘Send’ runat=’server’></{0}:CreditCardForm2>”)]
public class CreditCardForm2 : Control
This attribute instructs the designer to add the following line to the .aspx page when the page developer drags CreditCardForm2 from the Toolbox onto the designer surface:
<ccl:CreditCardForm2 runat=’server’ CardholderNameText=’Cardholder Full Name’ CreditCardNoText=’Credit Card Number’ PaymentMethodText=’Payment Options’ SubmitButtonText=’Send’></ccl:CreditCardForm2>
Assembly-Level Attributes
As discussed, when page developers drag a CreditCardForm2 control from the Toolbox onto the design
surface, the designer adds the following two lines to the .aspx file:
<%@ Register Assembly=”CustomComponents” Namespace=”CustomComponents”
TagPrefix=”cc1” %>
…
<cc1:CreditCardForm2 ID=”CreditCardForm2” runat=”server”/>
Notice that the designer uses the default cc1 as the prefix. You can add the following assembly-level attribute to the AssemblyInfo.cs file to instruct the designer to use “custom” as the tag prefix:
using System.Web.UI;
[assembly: TagPrefix(“CustomComponents”,”custom”)]
The HtmlTextWriter-Related Enumerations
public class CreditCardForm3 : CreditCardForm2
{
protected override void Render(HtmlTextWriter writer)
{
writer.AddStyleAttribute(HtmlTextWriterStyle.Width,“287px”);
writer.AddStyleAttribute(HtmlTextWriterStyle.Height, “124px”);
writer.AddStyleAttribute(HtmlTextWriterStyle.BorderWidth, “0”);
writer.AddAttribute(HtmlTextWriterAttribute.Id, “mytable”);
writer.RenderBeginTag(HtmlTextWriterTag.Table);
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.RenderBeginTag(HtmlTextWriterTag.Td);
writer.Write(PaymentMethodText);
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Td);
writer.AddAttribute(HtmlTextWriterAttribute.Name, “PaymentMethod”);
writer.AddAttribute(HtmlTextWriterAttribute.Id, “PaymentMethod”);
writer.AddStyleAttribute(HtmlTextWriterStyle.Width, “100%”);
writer.RenderBeginTag(HtmlTextWriterTag.Select);
writer.AddAttribute(HtmlTextWriterAttribute.Value, “0”);
The HtmlTextWriter class exposes one method for rendering each of the preceding parts as follows:
RenderBeginTag: Renders or generates the opening tag of an HTMLelement.
AddAttribute: This method is called once for each attribute to generate or render the attribute on the opening tag of the HTMLelement. This method must be called before RenderBeginTag.
AddStyleAttribute: This method is called once for each style attribute to generate or render the attribute as part of the style attribute of the HTMLelement. This method must also be called before RenderBeginTag. ASP.NET automatically generates a single attribute named style that contains all of the style attributes such as width, height, and so on. In other words, multiple calls of the AddStyleAttribute method are accumulated in a single style attribute on the opening tag of the element.
Write: Recall that an HTMLelement can contain text, other elements, or both. Use the Write method to generate any type of textual content such as string, int, float, and so on. You should use the RenderBeginTag, AddAttribute, AddStyleAttribute, and RenderEndTag methods to generate non-textual content, that is, child elements of an element.
RenderEndTag: Renders or generates the closing tag of an HTMLelement.
writer.AddStyleAttribute(HtmlTextWriterStyle.Width, “287px”);
writer.AddStyleAttribute(HtmlTextWriterStyle.Height, “124px”);
writer.AddStyleAttribute(HtmlTextWriterStyle.BorderWidth, “0”);
writer.AddAttribute(HtmlTextWriterAttribute.Id, “mytable”);
writer.RenderBeginTag(HtmlTextWriterTag.Table);
…
Writer.RenderEndTag();
State Management
public class CreditCardForm4 : CreditCardForm3
{
public override string PaymentMethodText
{
get { return ViewState[“PaymentMethodText”] != null ?
(string)ViewState[“PaymentMethodText”] : “PaymentMethod”; }
set { ViewState[“PaymentMethodText”] = value; }
}
public override string CreditCardNoText
{
get { return ViewState[“CreditCardNoText”] != null ?
(string)ViewState[“CreditCardNoText”] : “CreditCardNo”; }
set { ViewState[“CreditCardNoText”] = value; }
}
After converting each object to its string representation, ASP.NET stores these string values to a hidden field named __VIEWSTATE and sends them to the client. Therefore, the size of the string representations of the objects you store in ViewState matters.
When it comes to storing objects to ViewState you must keep the following two important things in mind:
ViewState is optimized to convert certain types such as System.String, System.Int32, System.Boolean, System.Drawing.Color, System.Unit, and Hashtable, Array, and ArrayList of Int32, Boolean, Color, and Unit values. If your custom control needs to store
other types to ViewState, you should write a custom type converter that is optimized to convert your custom type to its string representation.
Because the string representations of the objects you add to ViewState are stored on the ASP.NET page, you must store only necessary information to ViewState to reduce the size of the ASP.NET page. For example, you shouldn’t store values that you can easily evaluate for each
request.
Filed under: Uncategorized | Leave a comment »