Implementing a Custom Typed Style The MyPanelStyle Example


Implementing a Custom Typed Style ” The MyPanelStyle Example

We'll now demonstrate how to implement and use a custom typed style by creating a MyPanel control and its associated typed style, MyPanelStyle . The MyPanel control is similar to the ASP.NET Panel control, which allows a page developer to add controls to its Controls collection by nesting them within the control's tags. In a visual designer, you can do this by dragging controls onto the Panel 's design surface.

The ASP.NET Panel control does not have an associated PanelStyle and does not follow the recommended pattern of encapsulating style- related behavior in a typed style. Instead, Panel defines its style properties just as it defines other nonstyle properties. We'll demonstrate the technique that you should follow to add style properties by implementing a MyPanelStyle typed style and delegating the style functionality of the MyPanel control to it. In terms of functionality, MyPanel is identical to the Panel control and exposes the three style properties in the following list. Note that these properties are actually properties of the MyPanelStyle typed style.

  • BackImageUrl

    Specifies the URL for a background image.

  • HorizontalAlign

    Specifies the horizontal alignment for the added controls.

  • Wrap

    Specifies whether to enable wrapping for the added content.

We'll first show how the MyPanel control uses the MyPanelStyle typed style, and then we'll describe MyPanelStyle . Listing 11-3 shows the code for the MyPanel control.

Listing 11-3 MyPanel.cs
 usingSystem; usingSystem.ComponentModel; usingSystem.ComponentModel.Design; usingSystem.Drawing.Design; usingSystem.Web.UI; usingSystem.Web.UI.Design; usingSystem.Web.UI.WebControls; namespaceMSPress.ServerControls{ 
 [ Designer(typeof(MSPress.ServerControls.Design.MyPanelDesigner) ParseChildren(false), PersistChildren(true) ] publicclassMyPanel:WebControl{ publicMyPanel():base(HtmlTextWriterTag.Div){ } [ Bindable(true), Category("Appearance"), DefaultValue(""), Editor(typeof(ImageUrlEditor),typeof(UITypeEditor)), Description("TheURLforthebackgroundimage") ] publicvirtualstringBackImageUrl{ get{ if(ControlStyleCreated){ return((MyPanelStyle)ControlStyle).BackImageUrl; } returnString.Empty; } set{ ((MyPanelStyle)ControlStyle).BackImageUrl=value; } } [ Bindable(true), Category("Layout"), DefaultValue(HorizontalAlign.NotSet), Description("TheHorizontalAlignment") ] publicvirtualHorizontalAlignHorizontalAlign{ get{ if(ControlStyleCreated){ return ((MyPanelStyle)ControlStyle).HorizontalAlign; } returnHorizontalAlign.NotSet; } 
 set{ ((MyPanelStyle)ControlStyle).HorizontalAlign=value; } } [ Bindable(true), Category("Layout"), DefaultValue(true), Description("Specifieswhethercontentwrapswithinthepanel") ] publicvirtualboolWrap{ get{ if(ControlStyleCreated){ return((MyPanelStyle)ControlStyle).Wrap; } returntrue; } set{ ((MyPanelStyle)ControlStyle).Wrap=value; } } protectedoverrideStyleCreateControlStyle(){ returnnewMyPanelStyle(ViewState); } } } 

The MyPanel control overrides the CreateControlStyle method to return an instance of the MyPanelStyle style. This indirectly causes the returned MyPanelStyle instance to be assigned to the ControlStyle property. As we described in the "Styles Overview" section, the ControlStyle property is read-only and is indirectly set when its accessor invokes the CreateControlStyle method. Notice that CreateControlStyle passes the MyPanel control's ViewState into the constructor of MyPanelStyle . When you create a new style for your control in CreateControlStyle , you must pass your control's ViewState into the Style constructor so that the style object uses the same StateBag as your control. If you are overriding existing style properties, you should not create a new Style instance, as we saw in the Spreadsheet example in the previous section.

MyPanel also defines new style properties by exposing properties of MyPanelStyle as its own top-level properties. As we described in the previous paragraph, the type of the ControlStyle property is MyPanelStyle .

MyPanel also has a designer that is associated with it via the DesignerAttribute . The code for the designer is included with the book's sample files. Designers are explained in Chapter 15, "Design-Time Functionality."

We'll now implement the MyPanelStyle class that we used in the MyPanel control. These are the key steps in implementing a typed style:

  1. Create a class that derives from System.Web.UI.WebControls.Style . The object model of the Style class is listed in Appendix B.

  2. Define properties that your style will offer to a control. Store the properties in your style's ViewState dictionary.

  3. Override the CopyFrom and MergeWith methods to copy from or merge the properties you defined with the properties of a given style.

  4. Override the Reset method to remove the properties you added to ViewState .

  5. Override the AddAttributesToRender method to generate HTML and CSS attributes as part of the rendering process.

Listing 11-4 contains the code for the MyPanelStyle typed style.

Listing 11-4 MyPanelStyle.cs
 usingSystem; usingSystem.ComponentModel; usingSystem.Web.UI; usingSystem.Web.UI.WebControls; namespaceMSPress.ServerControls{ publicclassMyPanelStyle:Style{ internalconstintPROP_BACKIMAGEURL=1; internalconstintPROP_HORIZONTALALIGN=2; internalconstintPROP_WRAP=3; publicMyPanelStyle(){ } publicMyPanelStyle(StateBagbag):base(bag){ } 
 [ Bindable(true), Category("Appearance"), DefaultValue(""), Description("ThebackgroundimageofthePanel"), NotifyParentProperty(true) ] publicvirtualstringBackImageUrl{ get{ if(IsSet(PROP_BACKIMAGEURL)){ return(string)ViewState["BackImageUrl"]; } returnString.Empty; } set{ ViewState["BackImageUrl"]=value; } } [ Bindable(true), Category("Layout"), DefaultValue(HorizontalAlign.NotSet), Description("ThehorizontalalignmentofthePanel'scontents"), NotifyParentProperty(true) ] publicvirtualHorizontalAlignHorizontalAlign{ get{ if(IsSet(PROP_HORIZONTALALIGN)){ return (HorizontalAlign)ViewState["HorizontalAlign"]; } returnHorizontalAlign.NotSet; } set{ if(value<HorizontalAlign.NotSet value>HorizontalAlign.Justify){ thrownewArgumentOutOfRangeException("value"); } ViewState["HorizontalAlign"]=value; } } protectednewinternalboolIsEmpty{ 
 get{ returnbase.IsEmpty&& !IsSet(PROP_BACKIMAGEURL)&& !IsSet(PROP_HORIZONTALALIGN)&& !IsSet(PROP_WRAP); } } [ Bindable(true), Category("Layout"), DefaultValue(true), Description("WhetherthePanel'scontentscanwraparound"), NotifyParentProperty(true) ] publicvirtualboolWrap{ get{ if(IsSet(PROP_WRAP)){ return(bool)ViewState["Wrap"]; } returntrue; } set{ ViewState["Wrap"]=value; } } publicoverridevoidAddAttributesToRender(HtmlTextWriterwriter,WebControlowner){ base.AddAttributesToRender(writer,owner); if(IsSet(PROP_BACKIMAGEURL)){ strings=BackImageUrl; if(s.Length>0){ if(owner!=null){ s=owner.ResolveUrl(s); } writer.AddStyleAttribute(HtmlTextWriterStyle.BackgroundImage, "url("+s+")"); } } 
 if(IsSet(PROP_HORIZONTALALIGN)){ HorizontalAlignhAlign=HorizontalAlign; if(hAlign!=HorizontalAlign.NotSet){ TypeConverterhac= TypeDescriptor.GetConverter(typeof(HorizontalAlign)); writer.AddAttribute(HtmlTextWriterAttribute.Align, hac.ConvertToInvariantString(hAlign)); } } if(IsSet(PROP_WRAP)){ boolwrap=Wrap; if(!Wrap) writer.AddAttribute(HtmlTextWriterAttribute.Nowrap, "nowrap"); } } publicoverridevoidCopyFrom(Styles){ if(s!=null){ base.CopyFrom(s); if(sisMyPanelStyle){ MyPanelStylemps=(MyPanelStyle)s; if(!mps.IsEmpty){ if(mps.IsSet(PROP_BACKIMAGEURL)) this.BackImageUrl=mps.BackImageUrl; if(mps.IsSet(PROP_HORIZONTALALIGN)) this.HorizontalAlign=mps.HorizontalAlign; if(mps.IsSet(PROP_WRAP)) this.Wrap=mps.Wrap; } } } } internalboolIsSet(intpropNumber){ stringkey=null; switch(propNumber){ casePROP_BACKIMAGEURL: key="BackImageUrl"; break; casePROP_HORIZONTALALIGN: key="HorizontalAlign"; break; 
 casePROP_WRAP: key="Wrap"; break; }if(key!=null){ returnViewState[key]!=null; } returnfalse; } publicoverridevoidMergeWith(Styles){ if(s!=null){ if(IsEmpty){ //Mergingwithanemptystyleisequivalenttocopying, //whichismoreefficient. CopyFrom(s); return; } base.MergeWith(s); if(sisMyPanelStyle){ MyPanelStylemps=(MyPanelStyle)s; if(!mps.IsEmpty){ if(mps.IsSet(PROP_BACKIMAGEURL)&& !this.IsSet(PROP_BACKIMAGEURL)) this.BackImageUrl=mps.BackImageUrl; if(mps.IsSet(PROP_HORIZONTALALIGN)&& !this.IsSet(PROP_HORIZONTALALIGN)) this.HorizontalAlign=mps.HorizontalAlign; if(mps.IsSet(PROP_WRAP)&& !this.IsSet(PROP_WRAP)) this.Wrap=mps.Wrap; } } } } publicoverridevoidReset(){ base.Reset(); if(IsEmpty){ return; }if(IsSet(PROP_BACKIMAGEURL)) ViewState.Remove("BackImageUrl"); if(IsSet(PROP_HORIZONTALALIGN)) ViewState.Remove("HorizontalAlign"); 
 if(IsSet(PROP_WRAP)) ViewState.Remove("Wrap"); } } } 

The MyPanelStyle typed style performs the following tasks :

  • Derives from the Style class and defines three new properties, BackImageUrl , HorizontalAlign , and Wrap . These properties support the corresponding style properties in MyPanel . Notice that these properties are implemented by using the ViewState dictionary of the Style class.

  • Overrides the AddAttributesToRender method to render its properties as HTML attributes and CSS attributes. MyPanelStyle calls the method of the base class and then performs its own logic. The implementation of this method is almost identical to the implementation of the AddAttributesToRender method in a Web control, which we described in Chapter 8. However, there is a difference between the signature of this method in a typed style and the signature of this method in a Web control. The AddAttributesToRender method of Style takes two arguments, while the corresponding method of WebControl takes one argument. The second argument passed into the AddAttributesToRender method in Style is non-null when the style is used as the ControlStyle of a Web control; this second argument represents the control that owns the Style object.

  • Overrides the CopyFrom and MergeWith methods to copy or merge a given MyPanelStyle with itself. The CopyFrom method replaces existing property values with those properties that have been set in the Style instance that is passed into the method. The MergeWith method preserves the values of properties that are already set and copies other properties that are set in the Style instance that is passed into the method. Both of these methods invoke the corresponding methods of the base class and then perform their own logic.

  • Overrides the Reset method to remove the properties it added to ViewState . This method invokes the corresponding method of the base class and then performs its own logic.



Developing Microsoft ASP. NET Server Controls and Components
Developing Microsoft ASP.NET Server Controls and Components (Pro-Developer)
ISBN: 0735615829
EAN: 2147483647
Year: 2005
Pages: 183

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