Radcombobox sorting using header template

3 Answers 578 Views
ComboBox
Gavin
Top achievements
Rank 1
Iron
Gavin asked on 31 Oct 2022, 12:13 AM

I have a radcombobox that uses a headertemplate and an itemtemplate and I would like my users to be able to sort by clicking on the text from the headertemplate.

Here is the radcombobox. It works and it's pretty simple but I can't work out how to get it to sort the items based on clicking text in the header.

                <telerik:RadComboBox ID="rcbEmp2" runat="server" Width="570px" AutoPostBack="true"
                        MarkFirstMatch="true" HighlightTemplatedItems="true" AppendDataBoundItems="true" >
                        <HeaderTemplate>
                            <ul>
                                <li>Employee</li>
                                <li>Miles</li>
                                <li>Shifts</li>
                                <li>Availability</li>
                            </ul>
                        </HeaderTemplate>
                        <ItemTemplate>
                            <ul>
                                <li><asp:Label runat="server" ID="lbEmpNameg" Text='<%# Eval("EmpFullName")%> '></asp:Label></li>
                                <li><asp:Label runat="server" ID="Label1" Text='<%# Eval("KsDistance")%> '></asp:Label></li>
                                <li><%# DataBinder.Eval(Container.DataItem, "ThisWeeksDemoCount")%></li>
                                <li><%# DataBinder.Eval(Container.DataItem, "AvailText")%></li>
                            </ul>
                        </ItemTemplate>
                    </telerik:RadComboBox>

 

Thanks in advance!

3 Answers, 1 is accepted

Sort by
0
Doncho
Telerik team
answered on 02 Nov 2022, 05:45 PM

Hi Gavin,

To sort the items in RadComboBox you can use one of the dedicated server-side methods

  • RadComboBox1.SortItems()
  • RadComboBox1.Items.Sort()

Both these methods accept one parameter of type IComparer that can be used for defining a custom sorting order based on a property of the RadComboBoxItem (Text, Value, Checked, or some Custom Attributes). 

I would suggest you review our Implement Custom Sorting article. There you can find a sample of Custom Sorting implementation where ComboBoxItems are ordered by their value.

To trigger the custom sorting in the current case, you can possibly use LinkButtons in the HeaderTemplate and handle their server-side Click event to execute the desired custom sorting procedure.

I hope this information will help you achieve the desired behavior.

Kind regards,
Doncho
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

Gavin
Top achievements
Rank 1
Iron
commented on 17 Nov 2022, 02:25 AM

Thanks Doncho!

I managed to get that working server side however clicking on the link buttons causes a postback and the RadComboBox to close.

Because I can't have that happen I looked at client side sorting and I found this Sorting radcombobox in client side in UI for ASP.NET AJAX | Telerik Forums

It's pretty good  however because I'm using a HeaderTemplate and ItemTemplate 2 problems occured:-

1. I don't know how to get the values from the ItemTemplate to sort by them.

2. Because it is clearing the items then re-adding them back it loses the info in my ItemTemplate and only gives me the DataTextField. (Picture Below)

The sorting works but losing the other info in my ItemTemplate can't happen.

Is there a way that I can do it where it doesn't postback and it keeps the info in my ItemTemplate columns.

Thanks in advance!

 

Gavin

 

 

 

Doncho
Telerik team
commented on 21 Nov 2022, 02:41 PM

Hi Gavin,

You can use the ItemDataBound event of the Combo to store the additional fields as custom attributes of each combo Item:

Then you can use these custom attributes both to populate the combo and also to reach the specific values for each item on the client side and process them in the desired way:

Gavin
Top achievements
Rank 1
Iron
commented on 22 Nov 2022, 10:16 AM

Hi Doncho,

When I try to use the ItemDataBound event I get the following error.

 

Here is what e.Item.DataItem is returning

{ EmployeeID = 716, EmpFullName = "Feryal Allaoui", FirstName = "Feryal", LastName = "Allaoui", TrainingSpare = false, AreaSpare = false, KsDistance = "11.06", ThisWeeksDemoCount = 0, fnIEA = 0, AvailText = "" ... }

Sorry I didn't get very far before hitting this hurdle.

 

Cheers

Gavin

Gavin
Top achievements
Rank 1
Iron
commented on 23 Nov 2022, 03:01 AM

Hi Doncho,

After a lot of  time and research I found that the ItemDataBound event does not work for a RadComboBox when trying to retrieve the data like this DataRowView dataItem = (DataRowView)e.Item.DataItem;

I have managed to retrieve the information in the ItemDataBound event like this.

            Label lblDemoCount = item.FindControl("lblDemoCount") as Label;
            string demoCount = lblDemoCount.Text;
            if (!string.IsNullOrEmpty(demoCount))
            {
                item.Attributes["thedemoCount"] = demoCount;
            }

I have also managed to add it to an array using a loop like this

                    tempArray[i][3] = rcbItems.getItem(i).get_attributes().getAttribute("thedemoCount");

The only thing that I cannot see how to do is put it back into the RadComboBox.

I could put it into a label or anything really but can't work it out.

Here is what I'm trying

comboItem.get_attributes().setAttribute("thedemoCount", [i][3]);

comboItem.get_attributes().setAttribute("lblDemoCount", [i][3]);

Here is where I'm trying to put it 

<li class="col2g"><%# DataBinder.Eval(Container, "Attributes['thedemoCount']") %> </li>

 

Thanks in advance

Or I've tried here

<li class="col2g"><asp:Label runat="server" ID="lblDemoCount" Text='<%# DataBinder.Eval(Container.DataItem, "ThisWeeksDemoCount")%>' Visible="true"></asp:Label> </li>

Doncho
Telerik team
commented on 25 Nov 2022, 08:15 AM

Hi Gavin,

In the ItemDataBound you can reach the object instance that is bound to the current ComboBox item.

For instance, If ComboBox is bound to a DataTable object, the e.Item.DataItem will return the DataRowView bound to the current item. The e.Item.DataItem is holding an object of type object and it needs to be cast to the proper type. Looking at the error message you got, it seems that the Combo is bound to a collection of anonymous objects, and casting such objects as DataRowView fails.

Instead, I would suggest you consider defining a custom class with the same properties as the one currently used in the anonymous objects. Binding a collection of strongly typed objects to the RadComboBox will allow you to use the ItemDataBound event to reach each separate object instance and cast it to its type, hence reaching the values in its properties:

E.g. RadComboBox1.DataSource is set to List<MyCustomClass> and in ItemDataBound event:

MyCustomClass dataItem = e.Item.DataItem as MyCustomClass;

To be able to provide you with more accurate assistance it would be helpful if you share the current version of the RadComboBox declaration along with all the relevant code-behind logic. That way I can have a more clear overview of the specific scenario and come up with a more specific suggestion.

Gavin
Top achievements
Rank 1
Iron
commented on 01 Dec 2022, 12:57 AM

Hi Doncho,

I made a comment after my last one that I worked out how to get the data. I also can get it into the array using Javascript. I'm just having problems setting it.

Here is what I wrote which is also above.

Hi Doncho,

After a lot of  time and research I found that the ItemDataBound event does not work for a RadComboBox when trying to retrieve the data like this DataRowView dataItem = (DataRowView)e.Item.DataItem;

I have managed to retrieve the information in the ItemDataBound event like this.

            Label lblDemoCount = item.FindControl("lblDemoCount") as Label;
            string demoCount = lblDemoCount.Text;
            if (!string.IsNullOrEmpty(demoCount))
            {
                item.Attributes["thedemoCount"] = demoCount;
            }

I have also managed to add it to an array using a loop like this

                    tempArray[i][3] = rcbItems.getItem(i).get_attributes().getAttribute("thedemoCount");

The only thing that I cannot see how to do is put it back into the RadComboBox.

I could put it into a label or anything really but can't work it out.

Here is what I'm trying

comboItem.get_attributes().setAttribute("thedemoCount", [i][3]);

comboItem.get_attributes().setAttribute("lblDemoCount", [i][3]);

Here is where I'm trying to put it 

<li class="col2g"><%# DataBinder.Eval(Container, "Attributes['thedemoCount']") %> </li>

 

Thanks in advance

Or I've tried here

<li class="col2g"><asp:Label runat="server" ID="lblDemoCount" Text='<%# DataBinder.Eval(Container.DataItem, "ThisWeeksDemoCount")%>' Visible="true"></asp:Label> </li>

Gavin
Top achievements
Rank 1
Iron
commented on 20 Jan 2023, 06:16 AM

Hi,

I was just wondering if there was any update on this.

I still can't see how it can be done without post back.

Gavin
Top achievements
Rank 1
Iron
commented on 06 Mar 2023, 10:40 AM

I'm guessing this won't be answered which makes me also guess that it can't be done...
0
Doncho
Telerik team
answered on 09 Mar 2023, 09:42 AM

Hi Gavin,

Sorry for the delay with this case.

I am attaching a sample demonstration of how you can bind multiple fields as Attributes of the ComboBox items.

Using the default server-side Sorting capabilities of the Control you can implement a custom sorting mechanism based on any of the Attributes bound to the Combo Items.

Please give it a try review the implementation and see if you can reuse the approach for the current case.

Any sorting that applies on the client side would require a custom JavaScript approach that extends the default functionalities of the control. Although such a solution could be possible, it could be quite tricky to implement and will go beyond the supported features of the Control.

To be able to run the sample you will need to add the Telerik.Web.UI.dll in the bin folder of the project.

Please let me know if any further questions come up.

Kind regards,
Doncho
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

Gavin
Top achievements
Rank 1
Iron
commented on 13 Mar 2023, 07:51 AM

Thank you so much! I can't wait to give this a try!!!
Gavin
Top achievements
Rank 1
Iron
commented on 24 Mar 2023, 04:31 AM

Hi,

Thanks for your answer and sorry for the delay. I've spent days trying to work it out again and in the end it looks like it just can't happen. The whole point of what I'm asking is that it does not postback.

The example you gave posts back. 

I can get all of the values in JS into an array, clear the old radcombobox but cannot set them again.

I've taken another approach like this.

Add this link button into the header

 <asp:LinkButton ID="LinkButton2" runat="server" Text="TestSortMiles" OnClientClick="sortComboByMiles(); return false;"></asp:LinkButton>

Add this JS function

           function sortComboByMiles()
           {

               $find("<%=RadAjaxManager16.ClientID%>").ajaxRequest('sortComboByMiles');
           }

Add this in Code behind

protected void RadAjaxManager1_AjaxRequest(object sender, AjaxRequestEventArgs e)
{

           if (e.Argument == "sortComboByMiles")
            {
                RadComboBox rcbSuggestedEmp = sender as RadComboBox;
                if (hfrcbSuggestedEmpMilesAscDesc.Value == "Asc")
                {

                    rcbSuggestedEmp.Sort = RadComboBoxSort.Ascending;
                    hfrcbSuggestedEmpMilesAscDesc.Value = "Desc";
                }
                else
                {
                    rcbSuggestedEmp.Sort = RadComboBoxSort.Descending;
                    hfrcbSuggestedEmpMilesAscDesc.Value = "Asc";
                }
                // rcbEmp2.SortItems(new SortComboItemsByValue());
                rcbSuggestedEmp.SortItems(new SortSuggestedEmpComboItemsByMiles());
            }

}

 

The problem is that the RadComboBox "rcbSuggestedEmp" is inside a Radgrid. So I can't find it through the ajaxrequest.

Is there any way of doing this at all? It's a simple sort of a RadComboBox that's inside a Radgrid in an ItemTemplate. Without Posting back.

Cheers

Gavin

 

0
Doncho
Telerik team
answered on 28 Mar 2023, 10:37 AM

Hi Gavin,

Using RadAjaxManager and its ajaxRequest method seems quite a suitable solution for the case.

As the RadComboBox is nested in a template you can use the RadAjaxManager API to add the needed ajax setting programmatically, refer to the following resources:

Here is a sample modification of the sample code you can try:

ASPX

<telerik:RadAjaxManager ID="RadAjaxManager1" runat="server" OnAjaxRequest="RadAjaxManager1_AjaxRequest">
</telerik:RadAjaxManager>

<telerik:RadScriptBlock runat="server" ID="RadScriptBlock1">
    <script>
        function sortComboByMiles() {
            $find("<%=RadAjaxManager1.ClientID%>").ajaxRequest('sortComboByMiles');
        }
    </script>
</telerik:RadScriptBlock>

<telerik:RadComboBox ID="RadComboBox1" runat="server" Width="800px" DataSourceID="SqlDataSource1" AutoPostBack="true" DataTextField="OrderID" DataValueField="OrderID" CollapseAnimation-Type="None" ExpandAnimation-Type="None" OnLoad="RadComboBox1_Load"
    MarkFirstMatch="true" HighlightTemplatedItems="true" AppendDataBoundItems="true" DropDownCssClass="exampleRadComboBox" OnItemDataBound="RadComboBox1_ItemDataBound">
    <HeaderTemplate>
        <ul>
            <li class="col1">OrderID</li>
            <li class="col2">ShipName</li>
            <li class="col3">ShipCountry</li>
            <li class="col4">
                <asp:LinkButton ID="LinkButton2" runat="server" Text="TestSortMiles" OnClientClick="sortComboByMiles(); return false;"></asp:LinkButton>
            </li>
        </ul>
    </HeaderTemplate>
    <ItemTemplate>
        <ul>
            <li class="col1"><%# DataBinder.Eval(Container.DataItem, "OrderID")%></li>
            <li class="col2"><%# DataBinder.Eval(Container.DataItem, "ShipName")%></li>
            <li class="col3"><%# DataBinder.Eval(Container.DataItem, "ShipCountry")%></li>
            <li class="col4"><%# DataBinder.Eval(Container.DataItem, "Freight")%></li>
        </ul>
    </ItemTemplate>
</telerik:RadComboBox>

C#

protected void RadAjaxManager1_AjaxRequest(object sender, AjaxRequestEventArgs e)
{
    if (e.Argument == "sortComboByMiles")
    {
        switch (RadComboBox1.Sort)
        {
            case RadComboBoxSort.None:
                RadComboBox1.Sort = RadComboBoxSort.Ascending;
                break;
            case RadComboBoxSort.Ascending:
                RadComboBox1.Sort = RadComboBoxSort.Descending;
                break;
            case RadComboBoxSort.Descending:
                RadComboBox1.Sort = RadComboBoxSort.Ascending;
                break;
        }

        //RadComboBox1.Sort = RadComboBoxSort.Descending;
        RadComboBox1.SortItems(new SortComboItemsByValue());
        RadComboBox1.OpenDropDownOnLoad = true;
    }
}
protected void RadComboBox1_Load(object sender, EventArgs e)
{
    var combo = sender as RadComboBox;
    RadAjaxManager1.AjaxSettings.AddAjaxSetting(combo, combo);
    RadAjaxManager1.AjaxSettings.AddAjaxSetting(RadAjaxManager1, combo);
    RadComboBox1.OpenDropDownOnLoad = false;
}

Gavin
Top achievements
Rank 1
Iron
commented on 31 Mar 2023, 01:58 AM

Hi,

That all looks great and I can do that but I'm not sure if you read what I wrote.

The problem is that the RadComboBox "rcbSuggestedEmp" is inside a Radgrid. So I can't find it through the ajaxrequest.

protected void RadAjaxManager1_AjaxRequest(object sender, AjaxRequestEventArgs e)
{

 

           if (e.Argument == "sortComboByMiles")
            {
                RadComboBox rcbSuggestedEmp = sender as RadComboBox;
                if (hfrcbSuggestedEmpMilesAscDesc.Value == "Asc")
                {

                    rcbSuggestedEmp.Sort = RadComboBoxSort.Ascending;
                    hfrcbSuggestedEmpMilesAscDesc.Value = "Desc";
                }
                else
                {
                    rcbSuggestedEmp.Sort = RadComboBoxSort.Descending;
                    hfrcbSuggestedEmpMilesAscDesc.Value = "Asc";
                }
                // rcbEmp2.SortItems(new SortComboItemsByValue());
                rcbSuggestedEmp.SortItems(new SortSuggestedEmpComboItemsByMiles());
            }

 

}

 

How can I find the combo in the radGrid ItemTemplate through RadAjaxManager1_AjaxRequest(object sender, AjaxRequestEventArgs e)

If I can find the radcombobox in the AjaxRequestEvent above then I am home. I can do everything else but not find the Radcombobox in the RadAjaxManager1_AjaxRequest as I highlighted in yellow above.

In your code you have the following

protected void RadComboBox1_Load(object sender, EventArgs e)
{
    var combo = sender as RadComboBox;
    RadAjaxManager1.AjaxSettings.AddAjaxSetting(combo, combo);
    RadAjaxManager1.AjaxSettings.AddAjaxSetting(RadAjaxManager1, combo);
    RadComboBox1.OpenDropDownOnLoad = false;
}

 

However RadComboBox1 is not there because it is in a RadGrid. 

Cheers

Gavin

 


Doncho
Telerik team
commented on 05 Apr 2023, 06:23 AM

Hi Gavin,

Embedding this customized ComboBox in a Template makes the scenario quite more complicated and tricky to implement and this might require significant time and effort. 

I will invest some time experimenting with the scenario and I will come back to you with additional information.

Gavin
Top achievements
Rank 1
Iron
commented on 24 Feb 2025, 09:01 AM

Hi,

I have managed to get the sorting working in a stand alone radcombobox using RadAjaxManager and an ajaxrequest however the problem is that I am getting the list of data on the "OnItemsRequested" event and once I fire the sorting it works however when I go back to look into the radcombobox it fires the OnItemsRequested event again. It shouldn't be firing the event again I believe. 

Here is the RadCombobox 

                <telerik:RadComboBox ID="rcbEmp7" runat="server" Width="570px" SortCaseSensitive="false" BackColor="blue"
                        MarkFirstMatch="true" HighlightTemplatedItems="true" AppendDataBoundItems="true"  OnItemsRequested="rcbEmp7_ItemsRequested" EnableLoadOnDemand="True" >
                        <HeaderTemplate>
                            <ul>
                                <li class="col1gLengthened"><asp:LinkButton ID="lbtnRcbEmp2EmployeeHeader" runat="server" Text="Employee" OnClientClick ="sortComboByEmp(); return false;" ></asp:LinkButton></li>
                                <li class="col2g"><asp:LinkButton ID="lbtnRcbEmp2MilesHeader" runat="server" Text="Miles" OnClientClick="sortComboByMiles(); return false;"></asp:LinkButton></li>
                                <li class="col2g"><asp:LinkButton ID="lbtnRcbEmp2ShiftsHeader" runat="server" Text="# Shifts" OnClientClick="sortByShifts(); return false;"></asp:LinkButton></li>
                                <li class="col3g"><asp:Label ID="lbfinIEAgg" runat="server" Visible="false"></asp:Label></li>
                                <li class="col4g">Availability</li>
                            </ul>
                        </HeaderTemplate>
                        <ItemTemplate>
                            <ul>
                                <li class="col1gLengthened"><asp:Label runat="server" ID="lbEmpNameg" Text='<%# Eval("EmpFullName")%> '></asp:Label></li>
                                <li class="col2g"><asp:Label runat="server" ID="lblKsDistance" Text='<%# DataBinder.Eval(Container.DataItem, "KsDistance")%>'></asp:Label></li>
                                <li class="col2g"><asp:Label runat="server" ID="lblDemoCount" Text='<%# DataBinder.Eval(Container.DataItem, "ThisWeeksDemoCount")%>' Visible="true"></asp:Label><%# DataBinder.Eval(Container, "Attributes['thedemoCount']") %> </li>
                                <li class="col3g"><asp:Label ID="lbfinIEA" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "fnIEA")%>' Visible="false"></asp:Label></li>
                                <li class="col4g"><asp:Label ID="lbfinIEAText" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "AvailText")%>' ></asp:Label></li>
                            </ul>
                        </ItemTemplate>
                    </telerik:RadComboBox>

 

Here is the javascript for the LinkButton lbtnRcbEmp2EmployeeHeader in the header

           function sortComboByEmp() {
               $find("<%=RadAjaxManager16.ClientID%>").ajaxRequest('sortComboByEmpG');
           }

Of course the control rcbEmp7 is in my RadAjaxManager as an updatedControl

The sorting works fine if the datasource is normal however the problem is that I have about 700 of these on the page and they each get different data so I need them to only get the data on the "OnItemsRequested" event of the radcombobox

I hope that makes sense.

Gavin

 

 

Attila Antal
Telerik team
commented on 26 Feb 2025, 02:31 PM

Hi Gavin,

The ItemsRequested event of the ComboBox will trigger every single time the combo needs to list the items. With the Load On Demand functionality enabled, the items are loaded every time the dropdown opens.

The best way to achieve the sorting is to make the combo request the items again by calling the combo's requestItems() method (see RadComboBox Object) and send additional information to the server such as field name and sort order. When the event is triggered, you can access the additional info in the event arguments which you can use to fetch, filter, sort the data before returning it back to the combobox.

Note: In none of the scenarios is the RadAjaxManager, RadAjaxPanel or asp:UpdatePanels are involved. the ComboBox's Load on Demand functionality already makes AJAX calls to server.

If you need further assistance implementing this, please submit a support ticket and somebody from the Team will assist you.

Gavin
Top achievements
Rank 1
Iron
commented on 03 Mar 2025, 12:24 AM

Hi Attila,

The thing is that I don't want the ComboBox to trigger the itemsRequested event again. The data is the same, it is just sorted differently. 

In the standard scenario where I am not doing any sorting in the combobox the ItemsRequested event does not fire twice. It fires the first time I open the combobox and if I close it and open it again it will not fire a second time. That is what I want

I am guessing that the LoadOnDemand functionality sees the sorting as a postback and believes that it needs to get new data. Which it doesn't. It just needs to sort it.

Unfortunately I cannot disable the LoadOnDemand functionality.

What this means is that the combo has to get its items using LoadOnDemand then when I click an event to sort by a column and using the "ItemsRequested" event I can send the column name that I want sorted however it will postback and the combo will have to be loaded again. If the user then wants to sort  by employee again it will have to postback again and get all of the data again. This seems like a lot when it should be a simple javascript sort.

There is no difference in me simply setting a hidden field and when the user clicks on a header item I could just set the hidden field and use that value to do my sorting with the datasource since it  needs to get fresh data every time.

Am I missing something or is this a major flaw in the combobox?

Below is an example of my RadComboBox

 

 

 

Attila Antal
Telerik team
commented on 05 Mar 2025, 12:01 PM

Hi Gavin, 

I have to correct myself as was wrong. Earlier I said the Combo will request the items every time the dropdown opens. Actually, the items will only be requested automatically when the DropDown opens for the first time. Then the ItemsRequested event is triggered whenever you're typing in the input (changing the input text making the combo search for items based on that - requires the complete implementation of the Load On Demand Example functionality)

Server Templates with the LoadOnDemand functionality is not supported. For the correct implementation of the Load On Demand functionality, you can follow the instructions from the Load On Demand Example or ItemsRequested articles. With this approach the data binding in items will not work.

In order to use Server-Template, you must bind the ComboBox using the DataSource + DataBind() combination. The LoadOnDemand cannot be used in this case.

The ComboBox will not not make a PostBack unless the AutoPostBack property is set to true. 

<telerik:RadComboBox ID="RadComboBox1" AutoPostBack="true"

If a PostBack is made when you click on a control inside the Combo item, that is coming from the custom control. If you do not want that, you will need to prevent them from making PostBacks.

Summary

  • If you want to use Server Templates, you cannot use Load On Demand.
  • When using Load On Demand, you must create and add items to the ComboBox as demonstrated in the Load On Demand Example or ItemsRequested articles.
  • Sorting of Items is not supported out of the box and we do not have examples to share. If you want to sort the items, you will have to implement that additionally.
Tags
ComboBox
Asked by
Gavin
Top achievements
Rank 1
Iron
Answers by
Doncho
Telerik team
Share this question
or