Dropdownlist with optgroup using WebControlAdapters

1k Views Asked by At

I need to do a dropdownlist with optgroup. I found lots of guides and all foresee the use of WebControlAdapter this is the guide that I'm fllowing

I've added the class to my App_Code folder project:

 namespace admin.App_Code
 {
   public class DropDownListAdapter :
     System.Web.UI.WebControls.Adapters.WebControlAdapter
   {
    protected override void RenderContents(System.Web.UI.HtmlTextWriter writer)
    {
        // The current control being "adaptered" is available within context from the Control property
        DropDownList dropDownList = (DropDownList)Control;
        ListItemCollection items = dropDownList.Items;

        // Retrieve Optgrouping using LinQ
        var groups = (from p in items.OfType<ListItem>()
                      group p by p.Attributes["Group"] into g
                      select new { Label = g.Key, Items = g.ToList<ListItem>
        () });

        foreach (var group in groups)
        {
            if (!String.IsNullOrEmpty(group.Label))
            {
                writer.WriteBeginTag("optgroup");
                writer.WriteAttribute("label", group.Label);
                writer.Write(">");
            }

            int count = group.Items.Count();
            if (count > 0)
            {
                bool flag = false;
                for (int i = 0; i < count; i++)
                {
                    ListItem item = group.Items[i];

                    writer.WriteBeginTag("option");
                    if (item.Selected)
                    {
                        if (flag)
                        {
                            throw new HttpException("Multiple selected items not allowed");
                        }
                        flag = true;

                        writer.WriteAttribute("selected", "selected");
                    }

                    if (!item.Enabled)
                    {
                        writer.WriteAttribute("disabled", "true");
                    }

                    writer.WriteAttribute("value", item.Value, true);

                    if (this.Page != null)
                    {
                        this.Page.ClientScript.RegisterForEventValidation(dropDownList.UniqueID, item.Value);
                    }
                    writer.Write('>');
                    HttpUtility.HtmlEncode(item.Text, writer);
                    writer.WriteEndTag("option");
                    writer.WriteLine();
                }
            }
            if (!String.IsNullOrEmpty(group.Label))
            {
                writer.WriteEndTag("optgroup");
            }
        }
    }

    private Object _ViewState;

    protected override void OnLoad(EventArgs e)
    {
        if (Page.IsPostBack)
        {
            if (_ViewState != null)
            {
                Object[] groups = (Object[])_ViewState;
                DropDownList dropDownList = (DropDownList)Control;
                // Add saved optgroups to ListItems
                for (Int32 i = 0; i < groups.Length; i++)
                {
                    if (groups[i] != null)
                    {
                        dropDownList.Items[i].Attributes["Group"] = groups[i].ToString();
                    }
                }
            }
        }
        base.OnLoad(e);
    }

    protected override void LoadAdapterViewState(object state)
    {
        // Retrieve existing state
        _ViewState = state;
    }

    protected override object SaveAdapterViewState()
    {
        DropDownList dropDownList = (DropDownList)Control;
        Int32 count = dropDownList.Items.Count;
        Object[] values = new Object[count];

        // Retrieve Optgrouping from ListItem 
        for (int i = 0; i < count; i++)
        {
            values[i] = dropDownList.Items[i].Attributes["Group"];
        }
        return values;
    }
   }
}

 public static void loadDDLModelli(ref DropDownList ddl, List<dynamic> 
    objects)
    {
        Int16 cont = 0;
        ddl.Items.Clear();
        System.Web.UI.WebControls.ListItem li;
        String idModello = "";
        String nomeModello = "";
        String nomeBrand = "";
        String oggetto = "";

        List<System.Web.UI.WebControls.ListItem> items = new List<System.Web.UI.WebControls.ListItem>();
        foreach (var item in objects)
        {
            oggetto = item.ToString().Replace("{", "").Replace("}", "");
            idModello = oggetto.Split(',')[0].Split('=')[1].Trim();
            nomeModello = oggetto.Split(',')[1].Split('=')[1].Trim();
            nomeBrand = oggetto.Split(',')[2].Split('=')[1].Trim();
            li = new System.Web.UI.WebControls.ListItem(nomeBrand+" - "+nomeModello, idModello);
            li.Attributes["Group"] = nomeBrand;
            items.Add(li);
            cont++;
        };


        ddl.DataSource = items;
        ddl.DataBind();

        ddl.SelectedIndex = -1;
    }

I've added the folder App_Browser to my project (did not exist) and I've added the file BrowserFile.browser

<browsers>
  <browser refID="Default">
    <controlAdapters>
      <adapter controlType="System.Web.UI.WebControls.DropDownList"
       adapterType="admin.App_Code.DropDownListAdapter" />
    </controlAdapters>
  </browser>
</browsers>

in my page .aspx (that is in the same folder of the class DropDownListAdapter I have

 <asp:DropDownList runat="server" ID="ddlModelli" CssClass="form-control multipleSelect"></asp:DropDownList> 

that is filled in this way

public static void loadDDLModelli(ref DropDownList ddl, List<dynamic> objects)
    {
        Int16 cont = 0;
        ddl.Items.Clear();
        System.Web.UI.WebControls.ListItem li;
        String idModello = "";
        String nomeModello = "";
        String nomeBrand = "";
        String oggetto = "";

        List<System.Web.UI.WebControls.ListItem> items = new List<System.Web.UI.WebControls.ListItem>();
        foreach (var item in objects)
        {
            oggetto = item.ToString().Replace("{", "").Replace("}", "");
            idModello = oggetto.Split(',')[0].Split('=')[1].Trim();
            nomeModello = oggetto.Split(',')[1].Split('=')[1].Trim();
            nomeBrand = oggetto.Split(',')[2].Split('=')[1].Trim();
            li = new System.Web.UI.WebControls.ListItem(nomeBrand+" - "+nomeModello, idModello);
            li.Attributes["Group"] = nomeBrand;
            items.Add(li);
            cont++;
        };


        ddl.DataSource = items;
        ddl.DataBind();

        ddl.SelectedIndex = -1;
    }

the problem is that, when I watch the source code I do not have the optgroup tag but only options tag.

In fact, if I put a breakpoint in the first line of the method RenderContents this doesn't fire. What I'm doing wrong?

1

There are 1 best solutions below

0
On BEST ANSWER

I solved the issue. The problem was in the method LoadDDLModelli. Instead of setting DataSource and do the DataBind to the Dropdownlist passed via reference, I have to add ItemList singoularly (I cannot understand the difference)

public static void loadDDLModelli(ref DropDownList ddl, List<dynamic> objects)
{
    Int16 cont = 0;
    ddl.Items.Clear();
    System.Web.UI.WebControls.ListItem li;
    String idModello = "";
    String nomeModello = "";
    String nomeBrand = "";
    String oggetto = "";

    List<System.Web.UI.WebControls.ListItem> items = new List<System.Web.UI.WebControls.ListItem>();
    foreach (var item in objects)
    {
        oggetto = item.ToString().Replace("{", "").Replace("}", "");
        idModello = oggetto.Split(',')[0].Split('=')[1].Trim();
        nomeModello = oggetto.Split(',')[1].Split('=')[1].Trim();
        nomeBrand = oggetto.Split(',')[2].Split('=')[1].Trim();
        li = new System.Web.UI.WebControls.ListItem(nomeBrand+" - "+nomeModello, idModello);
        li.Attributes["Group"] = nomeBrand;
        items.Add(li);
        cont++;
    };


    //ddl.DataSource = items;
    //ddl.DataBind();

    foreach(ListItem i in items)
       ddl.Items.Add(i);

    ddl.SelectedIndex = -1;
}