已经完成了tab控件的必要的设计时支持和运行时输出,控件完整代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Web.UI.WebControls; using System.Web.UI; using System.ComponentModel; using System.Web.UI.Design.WebControls; using System.Web.UI.Design; using System.Security.Permissions; using System.Drawing; using System.ComponentModel.Design; using System.Web; using System.Web.UI.HtmlControls; namespace MyCtrls { public class TabControlDesigner : CompositeControlDesigner { private TabControl _tabControl; public TabControlDesigner() { this.ActiveTabViewIndex = 0; } private int ActiveTabViewIndex { get; set; } public override void Initialize(IComponent component) { base.Initialize(component); _tabControl = (TabControl)component; } public override bool AllowResize { get { return true; } } protected override void CreateChildControls() { base.CreateChildControls(); if (_tabControl.Controls.Count > 0) { Table layoutTable = (Table)_tabControl.Controls[0]; if (layoutTable != null) { //define regions for (var i = 0; i < layoutTable.Rows[0].Cells.Count; i++) { var cell = layoutTable.Rows[0].Cells[i]; if (string.IsNullOrEmpty(cell.Text)) cell.Width = new Unit(20); cell.Attributes[DesignerRegion.DesignerRegionAttributeName] = i.ToString(); if (i != ActiveTabViewIndex) cell.BackColor = System.Drawing.ColorTranslator.FromHtml(_tabControl.UnselectedHeaderBackColor); else cell.BackColor = System.Drawing.ColorTranslator.FromHtml(_tabControl.TabBackgroundColor); } layoutTable.Rows[1].Cells[0].BackColor = System.Drawing.ColorTranslator.FromHtml(_tabControl.TabBackgroundColor); layoutTable.Rows[1].Cells[0].Attributes[DesignerRegion.DesignerRegionAttributeName] = layoutTable.Rows[0].Cells.Count.ToString(); } } } public override String GetDesignTimeHtml(DesignerRegionCollection regions) { if (_tabControl.Controls.Count > 0) { Table layoutTable = (Table)_tabControl.Controls[0]; if (layoutTable != null) { for (var i = 0; i < layoutTable.Rows[0].Cells.Count; i++) { regions.Add(new DesignerRegion(this, string.Format("TabHeader_{0}", i))); } } EditableDesignerRegion editableRegion = new EditableDesignerRegion(this, string.Format("TabContent_{0}", ActiveTabViewIndex), false); regions.Add(editableRegion); regions[ActiveTabViewIndex].Highlight = true; } return base.GetDesignTimeHtml(); } protected override void OnClick(DesignerRegionMouseEventArgs e) { if (e.Region == null) return; if (!e.Region.Name.StartsWith("TabHeader")) return; var selectedIndex = int.Parse(e.Region.Name.Replace("TabHeader_", string.Empty)); if (selectedIndex != ActiveTabViewIndex) { ActiveTabViewIndex = selectedIndex; base.UpdateDesignTimeHtml(); } } public override string GetEditableDesignerRegionContent(EditableDesignerRegion region) { IDesignerHost host = (IDesignerHost)Component.Site.GetService(typeof(IDesignerHost)); if (host != null) { var selectedIndex = int.Parse(region.Name.Replace("TabContent_", string.Empty)); ITemplate template = _tabControl.Views[selectedIndex].ContentTemplate; if (template != null) return ControlPersister.PersistTemplate(template, host); } return String.Empty; } public override void SetEditableDesignerRegionContent(EditableDesignerRegion region, string content) { if (content == null) return; IDesignerHost host = (IDesignerHost)Component.Site.GetService(typeof(IDesignerHost)); if (host != null) { ITemplate template = ControlParser.ParseTemplate(host, content); if (template != null) { var selectedIndex = int.Parse(region.Name.Replace("TabContent_", string.Empty)); _tabControl.Views[selectedIndex].ContentTemplate = template; } } } } [ToolboxData("<{0}:TabControl runat=\"server\" width=\"500\"></{0}:TabControl>")] [Designer(typeof(TabControlDesigner))] [ParseChildren(typeof(TabView), DefaultProperty = "Views", ChildrenAsProperties = true)] public class TabControl : CompositeControl { public TabControl() { Views = new TabViewCollection(); this.Width = new Unit(500); this.TabBorderColor = "#E4E5E6"; this.TabBackgroundColor = "white"; this.UnselectedHeaderBackColor = "#F3F4F5"; this.HeaderTextStyle = "color:#1E5D7D;font-size:18px;text-decoration:none;font-family:Segoe UI,Trebuchet,Arial,Sans-Serif;"; this.HeaderBlockHeight = 37; this.HeaderLeftMargin = 15; this.HeaderBlockSpace = 5; this.HeaderTextHorizontalPadding = 18; } [PersistenceMode(PersistenceMode.InnerProperty)] public TabViewCollection Views { get; private set; } public Unit HeaderLeftMargin { get; set; } public Unit HeaderBlockHeight { get; set; } public Unit HeaderBlockSpace { get; set; } public Unit HeaderTextHorizontalPadding { get; set; } public string HeaderTextStyle { get; set; } public string TabBorderColor { get; set; } public string TabBackgroundColor { get; set; } public string UnselectedHeaderBackColor { get; set; } private int _SelectedIndex = 0; public int SelectedIndex { get { return _SelectedIndex; } set { if (_SelectedIndex != value) { _SelectedIndex = value; this.CreateChildControls(); } } } private bool IsDesignMode { get { return HttpContext.Current == null; } } protected override string TagName { get { return string.Empty; } } protected override void CreateChildControls() { Controls.Clear(); this.EnsureChildControls(); if (IsDesignMode) CreateDesignModeChildControls(); else CreateRunTimeChildControls(); ChildControlsCreated = true; } private void CreateDesignModeChildControls() { if (this.Views != null && this.Views.Count > 0) { //construct a table Table layoutTable = new Table(); layoutTable.CellSpacing = 1; layoutTable.BackColor = System.Drawing.ColorTranslator.FromHtml(this.TabBorderColor); layoutTable.BorderStyle = BorderStyle.None; layoutTable.Width = this.Width; layoutTable.Height = this.Height; //construct the header TableRow trHeader = new TableRow(); trHeader.HorizontalAlign = HorizontalAlign.Center; trHeader.BackColor = Color.LightBlue; trHeader.Height = new Unit(30); foreach (TabView view in this.Views) { var cellHeader = new TableCell(); cellHeader.BackColor = System.Drawing.ColorTranslator.FromHtml(this.UnselectedHeaderBackColor); cellHeader.Text = view.Header.HeaderText ?? string.Empty; cellHeader.Height = new Unit(30); trHeader.Cells.Add(cellHeader); } layoutTable.Rows.Add(trHeader); //construct the content var cellContent = new TableCell(); cellContent.ColumnSpan = trHeader.Cells.Count; cellContent.BackColor = Color.White; var trContent = new TableRow(); trContent.HorizontalAlign = HorizontalAlign.Center; trContent.Cells.Add(cellContent); layoutTable.Rows.Add(trContent); Controls.Add(layoutTable); } } private void CreateRunTimeChildControls() { HtmlGenericControl div = new HtmlGenericControl("div"); div.Style["width"] = this.Width.ToString(); div.Style["position"] = "relative"; div.Style["padding"] = new Unit(0).ToString(); div.Style["margin"] = new Unit(0).ToString(); div.Style["line-height"] = new Unit("100%").ToString(); div.Style["padding-top"] = this.HeaderBlockHeight.ToString(); HtmlGenericControl content = new HtmlGenericControl("div"); content.Style["border"] = string.Format("1px solid {0}", this.TabBorderColor); content.Style["height"] = new Unit("100%").ToString(); content.Style["width"] = new Unit("100%").ToString(); content.Style["background-color"] = this.TabBackgroundColor; div.Controls.Add(content); var headerContainer = new HtmlGenericControl("div"); headerContainer.Style["margin"] = new Unit(0).ToString(); headerContainer.Style["padding"] = new Unit(0).ToString(); headerContainer.Style["position"] = "absolute"; headerContainer.Style["top"] = new Unit(0).ToString(); for (var i = 0; i < this.Views.Count; i++) { var header = new HtmlGenericControl("div"); header.Style["padding-left"] = this.HeaderTextHorizontalPadding.ToString(); header.Style["padding-right"] = this.HeaderTextHorizontalPadding.ToString(); header.Style["padding-top"] = new Unit(0).ToString(); header.Style["padding-bottom"] = new Unit(0).ToString(); header.Style["height"] = new Unit(this.HeaderBlockHeight.Value - 1).ToString(); header.Style["margin-right"] = this.HeaderBlockSpace.ToString(); header.Style["float"] = "left"; header.Style["border"] = string.Format("1px solid {0}", this.TabBorderColor); header.Style["background-color"] = this.TabBackgroundColor; header.Style["text-align"] = "center"; header.Style["vertical-align"] = "middle"; header.Style["line-height"] = new Unit(this.HeaderBlockHeight.Value - 3).ToString(); if (i == 0) header.Style["margin-left"] = this.HeaderLeftMargin.ToString(); if (i == SelectedIndex) header.Style["border-bottom"] = string.Format("1px solid {0}", this.TabBackgroundColor); else header.Style["background-color"] = this.UnselectedHeaderBackColor; LinkButton link = new LinkButton(); link.Text = this.Views[i].Header.HeaderText ?? " "; link.Attributes["style"] = this.HeaderTextStyle; link.ID = string.Format("TabHeaderLink_{0}", i); link.Click += new EventHandler(link_Click); header.Controls.Add(link); headerContainer.Controls.Add(header); } div.Controls.Add(headerContainer); this.Controls.Add(div); if (Views.Count > 0) { if (Views[this.SelectedIndex].ContentTemplate != null) Views[this.SelectedIndex].ContentTemplate.InstantiateIn(content); } } void link_Click(object sender, EventArgs e) { var linkButtion = sender as LinkButton; var index = int.Parse((linkButtion.ID ?? string.Empty).Replace("TabHeaderLink_", string.Empty)); this.SelectedIndex = index; } } [Designer(typeof(TabViewDesigner))] public class TabView : CompositeControl { private TabViewHeader _Header = new TabViewHeader(); [PersistenceMode(PersistenceMode.InnerProperty)] public TabViewHeader Header { get { return _Header; } set { _Header = value; } } private ITemplate _ContentTemplate = null; [Browsable(false)] [PersistenceMode(PersistenceMode.InnerProperty)] [TemplateContainer(typeof(TabView))] public ITemplate ContentTemplate { get { return _ContentTemplate; } set { _ContentTemplate = value; } } protected override void CreateChildControls() { Controls.Clear(); if (_ContentTemplate != null) _ContentTemplate.InstantiateIn(this); base.CreateChildControls(); ChildControlsCreated = true; } } public class TabViewDesigner : CompositeControlDesigner { public override void Initialize(IComponent component) { base.Initialize(component); SetViewFlags(ViewFlags.TemplateEditing, true); } public override string GetDesignTimeHtml() { TabView control = Component as TabView; if (control != null) { if (control.ContentTemplate == null) { return CreatePlaceHolderDesignTimeHtml("Empty Content"); } } return base.GetDesignTimeHtml(); } private TemplateGroupCollection templateGroupCollection; public override TemplateGroupCollection TemplateGroups { get { if (templateGroupCollection == null) { templateGroupCollection = base.TemplateGroups; TemplateGroup contentTemplate = new TemplateGroup("ContentTemplate"); contentTemplate.AddTemplateDefinition(new TemplateDefinition(this, "ContentTemplate", Component, "ContentTemplate", false)); templateGroupCollection.Add(contentTemplate); } return templateGroupCollection; } } } public class TabViewHeader { public string HeaderText { get; set; } } public class TabViewCollection : List<TabView> { } }
控件用法:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication1.WebForm1" %> <%@ Register Assembly="MyCtrls" Namespace="MyCtrls" TagPrefix="cc1" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> </head> <body> <form id="form1" runat="server"> <div> <cc1:TabControl ID="TabControl1" runat="server" Width="493px"> <Views> <cc1:TabView ID="TabView1" runat="server"> <Header HeaderText="aaa" /> <ContentTemplate> <asp:Button ID="Button1" runat="server" Text="Button1" /> </ContentTemplate> </cc1:TabView> <cc1:TabView ID="TabView2" runat="server"> <Header HeaderText="bbb" /> <ContentTemplate> <asp:Button ID="Button2" runat="server" Text="Button2" /> </ContentTemplate> </cc1:TabView> <cc1:TabView ID="TabView3" runat="server"> <Header HeaderText="ccc" /> <ContentTemplate> <asp:Button ID="Button3" runat="server" Text="Button3" /> </ContentTemplate> </cc1:TabView> </Views> </cc1:TabControl> </div> </form> </body> </html>