ASP Webforms Controls
Control Types
Maybe it's just me, but the terms are confusing.
- Html server controls- html with runat="server"
- Webcontrols- asp:textbox etc (:WebControl)
- User controls- .ascx files with @Control instead of @Page, uncompiled and project scope.
- <%@Register TagPrefix="uc1" TagName="MyUC" src="a.ascx"%>
- if needed: <%@OutputCache Duration="240" VaryByParam="*"%> (and VaryByControl for each sub-control)
- cf [PartialCaching(60, "nine", "Name;Value", "")] public class Ucontrol
- Also load using <%@Reference Control="a.ascx"%> and Page.LoadControl(u.ascx)- nb can't new Control
- Change web form into UserControl (MSDN)
- Rename .aspx extension to .ascx
- Remove the html, body, and form elements
- Change @ Page to @ Control. Clean attributes to Language, AutoEventWireup, CodeFile, and Inherits. Add className
- Change code behind inherits from Page to UserControl.
- Custom controls- compiled and shared, of 3 types:
- Inherit and extend a specific Webcontrol
- Composite Webcontrols - Implement INamingContainer and override CreateChildControls
- EnsureChildControls() in case CreateChildControls not done yet!
- You don't have to override Render (see below) because child controls do it
- Generic- Inherit from Control or Webcontrol
- Render method (with HtmlTextWriter argument)
- Implement IPostBackDataHandler (for LoadPostData, return true to raise RaisePostDataChangedEvent)
Templated Controls
msdn (user controls) - msdn (custom controls)
- Add a property of type ITemplate (don't implement it- Asp.Net does it)
[PersistenceMode(PersistenceMode.InnerProperty), TemplateContainer(typeof(DateContainer))]
public virtual ITemplate Template
{
get { return templateValue; }
set { templateValue = value; }
}
- Optional: Create a nested class implementing INamingContainer (marker interface for fixing up IDs). It should have properties matching your public properties. This is the Container accessible in databinding.
public class DateContainer : Control, INamingContainer - In Page_Init() (UserControls) or CreateChildControls() (CustomControls) create the ItemContainer and put it in the placeholder
if (templateValue != null)
{
//create the container INamingContainer
DateContainer container = new DateContainer(Text, Date);
//put the ITemplate property into INamingContainer
templateValue.InstantiateIn(container);
//add to the controls (or a placeholder)
Controls.Add(container);
}
- Decorate the class with [ParseChildren(true)] (for intellisense)
AutoEventWireup
Events called twice? AutoEventWireup="true". Visual Studio automatically puts in Handles MyBase.Load
(VB) or this.Load += new System.EventHandler(this.Page_Load);
(C# InitializeComponent). [msdn].
In VS 2005, AutoEventWireup= true by default, but you also get the declarative onclick syntax. ([msdn2])
Events from User Controls
Exposing a gridview paging event (for a generic event with EventArgs, you don't need the delegate as the type is EventHandler; for custom events you might need a special class that extends EventArgs)
public delegate void PagingEventHandler(object sender, GridViewPageEventArgs e);
public event PagingEventHandler OnPaging;
protected void gvAssets_PageChanging(object sender, GridViewPageEventArgs e)
{
//raise the event
if (OnPaging != null) OnPaging(this, e);
}
Label vs Literal vs LiteralControl
To output text or html, use these (in order of preference):
- System.Web.UI.LiteralControl: The ASP parser turns all static html into this.
- WebControl.Literal preserves the .Text in ViewState.
- Label adds an html <span> around so it can be styled. Obvious probleems if you put certain html in it.
Default buttons and focus
Introduced in 2.0, setting the initial focus and default button is easy and really should be done on every page.
SetFocus(txtInput); //or txtInput.Focus();
Form.DefaultButton = btnSubmit.UniqueID; //not the id or clientId