Custom control in toolbox, intellisense?

D

Dave

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;
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>
 
T

Teemu Keiski

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


--
Teemu Keiski
ASP.NET MVP, AspInsider
Finland, EU
http://blogs.aspadvice.com/joteke



Dave said:
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;
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>
 
D

Dave

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?


Teemu Keiski said:
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


--
Teemu Keiski
ASP.NET MVP, AspInsider
Finland, EU
http://blogs.aspadvice.com/joteke



Dave said:
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;
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>

 
T

Teemu Keiski

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/ccctemplates.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/ContCrshCrsDB.asp
(see other control articles on the same series as well)


--
Teemu Keiski
ASP.NET MVP, AspInsider
Finland, EU
http://blogs.aspadvice.com/joteke




Dave said:
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?


Teemu Keiski said:
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


--
Teemu Keiski
ASP.NET MVP, AspInsider
Finland, EU
http://blogs.aspadvice.com/joteke



Dave said:
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;
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>

 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,742
Latest member
AshliMayer

Latest Threads

Top