Radcombobox sorting using header template

5 Answers 485 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!

5 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.

0
Gavin
Top achievements
Rank 1
Iron
answered 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!!!
0
Gavin
Top achievements
Rank 1
Iron
answered 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

 

Doncho
Telerik team
commented 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;
}

0
Gavin
Top achievements
Rank 1
Iron
answered 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.

Tags
ComboBox
Asked by
Gavin
Top achievements
Rank 1
Iron
Answers by
Doncho
Telerik team
Gavin
Top achievements
Rank 1
Iron
Share this question
or