Below is some custom control code to create a tab strip taken from ASP.NET
2.0 Unleashed by Stephen Walther. It works, but I need to clarify some
things...
1.) Both "ServerTabs" and "ServerTab" appear in the VS toolbox when I add
the control. How can I just get "ServerTabs" appear (i.e. ListItem doesn't
appear with DropDownList but it still appears in Intellisense like below).
The "ServerTab" is dependent on "ServerTabs" so I don't want it to appear on
the toolbox. When I try to hide it using [ToolboxItem(false)], it won't
appear in Intellisense then..how do I get it to work like this
<asp:DropDownList ID="ddwn1" runat="server">
<asp:ListItem></asp:ListItem>
</asp:DropDownList>
2.) In the code, ControlBuilder's GetChildControlType checks for a "tab"
tag. Can I get "tab" to appear in Intellinsense like the ListItem does for
the DropDownList??
HTML and .CS file below....
-----------------------------------
.CS
-----------------------------------
using System;
using System.Collections;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace myControls
{
[ControlBuilder(typeof(ServerTabsBuilder))]
[ParseChildren(false)]
public class ServerTabs : WebControl, IPostBackEventHandler
{
public int SelectedTabIndex
{
get
{
if (ViewState["SelectedTabIndex"] == null)
return 0;
else
return (int)ViewState["SelectedTabIndex"];
}
set
{
ViewState["SelectedTabIndex"] = value;
}
}
protected override void RenderContents(HtmlTextWriter writer)
{
for (int i = 0; i < this.Controls.Count; i++)
{
ServerTab tab = (ServerTab)this.Controls[i];
string eRef =
Page.ClientScript.GetPostBackClientHyperlink(this, i.ToString());
if (SelectedTabIndex == i)
writer.AddAttribute(HtmlTextWriterAttribute.Class, "tab
selectedTab");
else
writer.AddAttribute(HtmlTextWriterAttribute.Class, "tab");
writer.RenderBeginTag(HtmlTextWriterTag.Div);
writer.AddAttribute(HtmlTextWriterAttribute.Href, eRef);
writer.RenderBeginTag(HtmlTextWriterTag.A);
writer.Write(tab.Text);
writer.RenderEndTag(); // A
writer.RenderEndTag(); // Tab DIV
}
writer.Write("<br style='clear:both' />");
writer.AddAttribute(HtmlTextWriterAttribute.Class, "tabContents");
writer.RenderBeginTag(HtmlTextWriterTag.Div);
this.Controls[SelectedTabIndex].RenderControl(writer);
writer.RenderEndTag(); // Tab Contents DIV
}
protected override void AddParsedSubObject(object obj)
{
if (obj is ServerTab)
base.AddParsedSubObject(obj);
}
protected override HtmlTextWriterTag TagKey
{
get
{
return HtmlTextWriterTag.Div;
}
}
public void RaisePostBackEvent(string eventArgument)
{
SelectedTabIndex = Int32.Parse(eventArgument);
}
}
public class ServerTabsBuilder : ControlBuilder
{
public override Type GetChildControlType(string tagName, IDictionary
attribs)
{
if (String.Compare(tagName, "tab", true) == 0)
return typeof(ServerTab);
else
return null;
}
}
//[ToolboxItem(true)]
public class ServerTab : Control
{
private string _Text;
public string Text
{
get { return _Text; }
set { _Text = value; }
}
}
}
-----------------------------------
HTML
-----------------------------------
<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="WebFormServerTabs.aspx.cs" Inherits="WebFormServerTabs" %>
<%@ Register Assembly="CustomControls" Namespace="myControls"
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 id="Head1" runat="server">
<style type="text/css">
html
{
background-color:silver;
}
.tab
{
float:left;
position:relative;
top:1px;
background-color:#eeeeee;
border:solid 1px black;
padding:0px 15px;
margin-left:5px;
}
.tab a
{
text-decoration:none;
}
.selectedTab
{
background-color:white;
border-bottom:solid 1px white;
}
.tabContents
{
border:solid 1px black;
background-color:white;
padding:10px;
height:200px;
}
</style>
<title>Show ServerTabs</title>
</head>
<body>
<form id="form1" runat="server">
<cc1:ServerTabs ID="ServerTabs1" runat="server">
<tab Text="First Tab">Contents of first tab</tab>
<tab Text="Second Tab">Contents of second tab</tab>
<tab Text="Three Tab">Contents of three tab</tab>
</cc1:ServerTabs>
</form>
</body>
</html>
Teemu Keiski - 27 Jul 2006 09:54 GMT
Hi,
semantics between ServerTabs and DropDownList are bit different. First,
ListItem is not a control where as ServerTab is. DropDownList uses ListItem
objects to render out <OPTION> tags, but ListItems are never part of
DropDownList's Controls collection (they are not child controls of DDL).
ListItems have their own collection, ListItemCollection, which
DropDownList.Items property represents. When ListItems are specified in
declarative syntax, they are added to the Items collection, from where
DropDownList then iterates them at render time.
If you want this type of functionality, you would need to take a bit another
approach and have ServerTab as non-controls and available as complex
property (Tabs) on the ServerTabs control. It would certainly make the
control more complex since you would then need to have ITemplate properties
etc

Signature
Teemu Keiski
ASP.NET MVP, AspInsider
Finland, EU
http://blogs.aspadvice.com/joteke
> Below is some custom control code to create a tab strip taken from ASP.NET
> 2.0 Unleashed by Stephen Walther. It works, but I need to clarify some
[quoted text clipped - 186 lines]
> </body>
> </html>
Dave - 27 Jul 2006 14:13 GMT
Teemu,
Thank you! I would really like to learn more about this type of development.
Can you recommend sources on the topics you mentioned specifically using
ITemplate?
As for my specific questions.
1) Can I only show "ServerTabs" and hide "ServerTab" on the toolbox in VS?
In other words, don't show child controls on the toolbar.
2) If I implement the ControlBuilder using "tab" tags as checked in the
GetChildControlType, can I make "tab" tags part of Intellisense?
> Hi,
>
[quoted text clipped - 203 lines]
> > </body>
> > </html>
Teemu Keiski - 27 Jul 2006 15:10 GMT
1. Yes, by taking the change I mentioned and having ServerTab as non-control
(sure ToolBoxItem hides it, but also removes it from Intellisense)
2. Making tab available in Intellisense as I understand you wanting it,
requires you to have the collection property (for ServerTab objects) within
your custom control, in case you want it to work in sync with your question
1. Using ControlBuilder means that you take approach that content between
control's tags is mapped to child controls, while the approach I'm trying to
bring yto ou, is that content between control's tag is mapped to its
properties e.g you don't have control builder.
The best resource about control development is MSPress's book Developing
ASP.NET Server Control and Components. Then there are some good articles:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/ccc
templates.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/Con
tCrshCrsDB.asp
(see other control articles on the same series as well)

Signature
Teemu Keiski
ASP.NET MVP, AspInsider
Finland, EU
http://blogs.aspadvice.com/joteke
> Teemu,
>
[quoted text clipped - 228 lines]
>> > </body>
>> > </html>