|
Hi,
I am sure that even the latest Visual Studio 2010 supports in web components such as DropDownList or ListBox. A custom control can be built as like this post mentioned. But, I have a different solution to have like functionality with web controls. See the sample code below:
public void fillCountry(DropDownList drp){
SqlConnection conn = new SqlConnection();
conn.ConnectionString = "";
string sql = "select country, province from countryList order by country, province";
conn.Open();
SqlCommand cmd=new SqlCommand(sql, conn);
SqlDataReader dr = cmd.ExecuteReader();
string grph = "";
while (dr.Read())
{
ListItem drpg;
ListItem drpi;
if (grph != dr.GetSqlString(0).ToString())
{
drpg = new ListItem(dr.GetSqlString(0).ToString(), dr.GetSqlString(0).ToString());
grph = dr.GetSqlString(0).ToString();
drp.Items.Add(drpg);
drpg.Attributes.Add("disabled", "disabled");
drpg.Attributes.Add("style", "background-color:lightblue;");
}
drpi=new ListItem(dr.GetSqlString(1).ToString(), dr.GetSqlString(1).ToString());
drp.Items.Add(drpi);
grph = dr.GetSqlString(0).ToString();
}
conn.Close();
}
This code provides a list box with provinces under each country. Country is disabled as not to be selected and therefore I have added a background to highlight the group.
Hope this code will help. :
|
|
|
|
|
Your solution has a problem that If I click a button cause the page postback,then you will find that the attribute of "disabled" is missing!the country is enabled to be selected now.
|
|
|
|
|
Thanx a lot..... It's a good alternatively to the optgroup of HTML..; I was exhausted by finding the solution...but finally got one..
|
|
|
|
|
Hi,
Thanks for a nice article.
I wanted the DropdownList as in the example but I need the data from DB, but now Im unable to bind this from code behind as follows,
ddlCountry.DataSource = CountryCollection;
ddlCountry.DataBind();
In this the optGroup is region I have the region for each country in the collection. How can I set this property from code behind.
Regards
Sudheshna
|
|
|
|
|
Hi,
This is a very useful function, however you did not specific any terms of use for it. This makes it difficult for me to use in my company. Could you please let me know if this example is under The Code Project Open License (CPOL) or some other license. Or can you specify terms under which I can use this code. Seem a shame you need to do this for a code examples website, but I don't make the rules. If you are still monitoring this article and can state this, I would be grateful.
Thanks much
-Hal
|
|
|
|
|
Hi Hal,
Thanks for asking, I should have posted that information along with the article. You're free to use the code for personal or commercial applications but the usual disclaimers apply... I accept no responsibility for any loss arising out of the use of this code, etc. Cheers
|
|
|
|
|
Hi,
With the normal dropdown it works fine, when wrap it with the Ajax all the headers are getting displayed first and then all the items. Anybody had done using ajax
|
|
|
|
|
Thank you for the useful DropDownAdapter class, I am able to use it easy. Now, I want to turn this adapter into a ListBox. I changed the class to use:
ListBox list = this.Control as ListBox;
But, the label is not showing. What else do I need to do in the class to make it work for ListBox? FYI. I want to use the ListBox instead of DropDown because I want to have the multiple selection capabilities. Wanting to have the abilities to have "Select All" per group.
Thank you.
|
|
|
|
|
Hello,
I'm getting a event validation error when use your code. Is there any way to get around this other that turning event validation off?
Thanks!
Ken
|
|
|
|
|
HI , My Application is Running in D:/VSS Applicatiom/BulkSMS
I saved .CS file in App_Data Folder
now it giving me Error 52 Could not load type 'VSS Application.BulkSMS.App_Code.Adapters.DropDownListAdapter'. (D:\VSS Application\BulkSMS\App_Browsers\BrowserFile.browser line 4)
What should be the path fro "adapterType" in browser file
Plz Help me
|
|
|
|
|
Using VB.NET you solve this problem by adding in:
list.Page.ClientScript.RegisterForEventValidation(list.UniqueID, item.Value)
right after the For Each statement.
Hope this helps someone.
|
|
|
|
|
Thank you! It worked for me in VB.
|
|
|
|
|
Thanks! That exact same register line worked for me in C# VS 2013.
|
|
|
|
|
*****PLACE CLASS in App_Code.*****
Imports Microsoft.VisualBasic
Imports System
Imports System.Data
Imports System.Configuration
Imports System.Web
Imports System.Web.Security
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Web.UI.WebControls.WebParts
Imports System.Web.UI.HtmlControls
Imports System.Collections
Imports System.Collections.Generic
Namespace MyGUI.Adapters
Public Class DropDownListAdapter
Inherits System.Web.UI.WebControls.Adapters.WebControlAdapter
Protected Overrides Sub RenderContents(ByVal writer As System.Web.UI.HtmlTextWriter)
Dim list As DropDownList = Me.Control
Dim currentOptionGroup As String = ""
Dim renderedOptionGroups As New Collection
For Each item As ListItem In list.Items
If item.Attributes("OptionGroup") = "" Then
RenderListItem(item, writer)
Else
If currentOptionGroup <> item.Attributes("OptionGroup") Then
If currentOptionGroup <> "" Then
RenderOptionGroupEndTag(writer)
End If
currentOptionGroup = item.Attributes("OptionGroup")
RenderOptionGroupBeginTag(currentOptionGroup, writer)
End If
RenderListItem(item, writer)
End If
Next
If currentOptionGroup <> "" Then
RenderOptionGroupEndTag(writer)
End If
End Sub
Private Sub RenderListItem(ByVal item As ListItem, ByVal writer As HtmlTextWriter)
writer.WriteBeginTag("option")
writer.WriteAttribute("value", item.Value, True)
If (item.Selected) Then writer.WriteAttribute("selected", "selected", False)
For Each key As String In item.Attributes.Keys
writer.WriteAttribute(key, item.Attributes(key).ToString)
Next
writer.Write(HtmlTextWriter.TagRightChar)
HttpUtility.HtmlEncode(item.Text, writer)
writer.WriteEndTag("option")
writer.WriteLine()
End Sub
Private Sub RenderOptionGroupBeginTag(ByVal name As String, ByVal writer As HtmlTextWriter)
writer.WriteBeginTag("optgroup")
writer.WriteAttribute("label", name)
writer.Write(HtmlTextWriter.TagRightChar)
writer.WriteLine()
End Sub
Private Sub RenderOptionGroupEndTag(ByVal writer As HtmlTextWriter)
writer.WriteEndTag("optgroup")
writer.WriteLine()
End Sub
End Class
End Namespace
BROWSER FILE
<browsers>
<browser refID="Default">
<controlAdapters>
<adapter controlType="System.Web.UI.WebControls.DropDownList"
adapterType="MyGUI.Adapters.DropDownListAdapter" />
</controlAdapters>
</browser>
</browsers>
|
|
|
|
|
Hello,
I'm trying to use your code in an Web Project of VS2008 but I'm not able to find a way to do it.
What is not clear, for me that I'm newbe, where I've to put the Adpater Code.
Can you help me?
Thanks
Massimo
|
|
|
|
|
Hi,
It's pretty straight forward and has nothing to do with the version of the IDE you're using. All you need to do is as follows:
1.) Create a class somewhere containing your control adapter. I use /Code/Adapters for this, but you could put it anywhere. Note, this is not the App_Code folder, which is not used in web application projects.
2.) Add a browsers file to the special App_Browsers folder. If you dont already have this folder, you can add it by right clicking the project, then choose 'Add' then 'Add ASP.NET Folder', you'll see it in the list. You may choose what to name your file, but it must have the extension .browser
I generally keep the default BrowserFile.browser filename.
3.) In that file, you need to add some xml code, which tells the runtime to use your adapter when rendering the control. This code will look as follows:
<browsers>
<browser refID="Default">
<controlAdapters>
<adapter controlType="System.Web.UI.WebControls.AdRotator"
adapterType="My.Namespace.Project.Code.Adapters.AdRotatorAdaptor" />
</controlAdapters>
</browser>
</browsers>
That should do it. If you still struggle to get it working, there are many examples on control adapters out there, just Google away, you'll find something.
|
|
|
|
|
Thanks, your suggestion has been perfect.
Now everything works fine!
Massimo
|
|
|
|
|
Hi,
Is there any way so that we can set the style of the optgroup label to another appeareace, like normal text, italic, forecolor etc.
Thanks
|
|
|
|
|
Add some CSS!
optgroup { color:Red; }
option {color: Black;}
|
|
|
|
|
i try to do this with u'r code:
---Choose ---
Group1
--Item1
--Item2
ItemWithoutGroup
Group2
--Item4
--Item4
in u'r code if thegroup item we put :
ListItem item6 = new ListItem("Allosaurus", "6");
item6.Attributes["OptionGroup"] = "Dinosaurs";
and then i add the item without group after that line with this code only
ListItem item7 = new ListItem("Trex", "7");
it still assume the item7 also in the previous group.
modified on Wednesday, September 17, 2008 5:13 AM
|
|
|
|
|
Did anyone find a possible solution for mixing ungrouped items?
|
|
|
|
|
I found the issue and fixed that. Below is the fix (in VB.NET)
Protected Overloads Overrides Sub RenderContents(ByVal writer As HtmlTextWriter)
Dim list As DropDownList = TryCast(Me.Control, DropDownList)
Dim currentOptionGroup As String
Dim renderedOptionGroups As New List(Of String)()
Dim tagClosed As Boolean = True
For Each item As ListItem In list.Items
If item.Attributes("OptionGroup") Is Nothing OrElse item.Attributes("OptionGroup") = "" Then
If Not tagClosed Then RenderOptionGroupEndTag(writer) : tagClosed = True
RenderListItem(item, writer)
Else
currentOptionGroup = item.Attributes("OptionGroup")
If renderedOptionGroups.Contains(currentOptionGroup) Then
RenderListItem(item, writer)
Else
If tagClosed = False Then
RenderOptionGroupEndTag(writer)
tagClosed = True
End If
RenderOptionGroupBeginTag(currentOptionGroup, writer)
renderedOptionGroups.Add(currentOptionGroup)
RenderListItem(item, writer)
tagClosed = False
End If
End If
Next
If tagClosed = False Then
RenderOptionGroupEndTag(writer)
End If
End Sub
I hope that will help.
Sameers
|
|
|
|
|
I am using this adapter for listbox. Everything works fine except that optgroup structure disappears after PostBack. When I used following two functions for saving and loading viewstate it gives me error CS0115: 'ListAdapter.ListBoxAdapter.SaveViewState()': no suitable method found to override
The code I added for saving and loading viewstate is:
protected override object SaveViewState()
{
// Create an object array with one element for the CheckBoxList's
// ViewState contents, and one element for each ListItem in skmCheckBoxList
object[] state = new object[this.Items.Count + 1];
object baseState = base.SaveViewState();
state[0] = baseState;
// Now, see if we even need to save the view state
bool itemHasAttributes = false;
for (int i = 0; i < this.Items.Count; i++)
{
if (this.Items[i].Attributes.Count > 0)
{
itemHasAttributes = true;
// Create an array of the item's Attribute's keys and values
object[] attribKV = new object[this.Items[i].Attributes.Count * 2];
int k = 0;
foreach (string key in this.Items[i].Attributes.Keys)
{
attribKV[k++] = key;
attribKV[k++] = this.Items[i].Attributes[key];
}
state[i + 1] = attribKV;
}
}
// return either baseState or state, depending on whether or not
// any ListItems had attributes
if (itemHasAttributes)
return state;
else
return baseState;
}
protected override void LoadViewState(object savedState)
{
if (savedState == null) return;
// see if savedState is an object or object array
if (savedState is object[])
{
// we have an array of items with attributes
object[] state = (object[])savedState;
base.LoadViewState(state[0]); // load the base state
for (int i = 1; i < state.Length; i++)
{
if (state[i] != null)
{
// Load back in the attributes
object[] attribKV = (object[])state[i];
for (int k = 0; k < attribKV.Length; k += 2)
this.Items[i - 1].Attributes.Add(attribKV[k].ToString(), attribKV[k + 1].ToString());
}
}
}
else
// we have just the base state
base.LoadViewState(savedState);
}
Is there any complete solution for this?
|
|
|
|
|
First I have to thank the author for this post. It has helped me a lot in getting this to work. I thought I'd make a contribution to this code to make PastBacks work correctly.
public class DropDownListAdapter : System.Web.UI.WebControls.Adapters.WebControlAdapter {
public static readonly string OPTGROUPATTR = "OptionGroup";
Dictionary<string, string> optionGroups = new Dictionary<string, string>();
protected override void RenderContents(HtmlTextWriter writer) {
DropDownList list = this.Control as DropDownList;
string currentOptionGroup;
List<string> renderedOptionGroups = new List<string>();
foreach(ListItem item in list.Items) {
string keyString = item.Value + item.Text;
if(item.Attributes[OPTGROUPATTR] == null && !optionGroups.ContainsKey(keyString)) {
RenderListItem(item, writer);
} else {
if (item.Attributes[OPTGROUPATTR] != null)
currentOptionGroup = item.Attributes[OPTGROUPATTR];
else
{
currentOptionGroup = optionGroups[keyString];
}
if(renderedOptionGroups.Contains(currentOptionGroup)) {
RenderListItem(item, writer);
} else {
if(renderedOptionGroups.Count > 0) {
RenderOptionGroupEndTag(writer);
}
RenderOptionGroupBeginTag(currentOptionGroup, writer);
renderedOptionGroups.Add(currentOptionGroup);
RenderListItem(item, writer);
}
}
}
if(renderedOptionGroups.Count > 0) {
RenderOptionGroupEndTag(writer);
}
}
private void RenderOptionGroupBeginTag(string name, HtmlTextWriter writer) {
writer.WriteBeginTag("optgroup");
writer.WriteAttribute("label", name);
writer.Write(HtmlTextWriter.TagRightChar);
writer.WriteLine();
}
private void RenderOptionGroupEndTag(HtmlTextWriter writer) {
writer.WriteEndTag("optgroup");
writer.WriteLine();
}
private void RenderListItem(ListItem item, HtmlTextWriter writer) {
this.Page.ClientScript.RegisterForEventValidation(this.Control.UniqueID, item.Value);
writer.WriteBeginTag("option");
writer.WriteAttribute("value", item.Value, true);
if(item.Selected) {
writer.WriteAttribute("selected", "selected", false);
}
foreach(string key in item.Attributes.Keys) {
writer.WriteAttribute(key, item.Attributes[key]);
}
writer.Write(HtmlTextWriter.TagRightChar);
HttpUtility.HtmlEncode(item.Text, writer);
writer.WriteEndTag("option");
writer.WriteLine();
}
protected override object SaveAdapterViewState()
{
DropDownList list = this.Control as DropDownList;
string currentOptionGroup;
string keyString;
foreach (ListItem item in list.Items)
{
if (item.Attributes[OPTGROUPATTR] != null)
{
currentOptionGroup = item.Attributes[OPTGROUPATTR];
keyString = item.Value + item.Text;
optionGroups[keyString] = currentOptionGroup;
}
}
return optionGroups;
}
protected override void LoadAdapterViewState(object state)
{
optionGroups = state as Dictionary<string, string>;
}
}
|
|
|
|
|
Thanks Lamester,
This was helpful..
|
|
|
|
|