This is a migrated thread and some comments may be shown as answers.

Natural sort on custom sorting

1 Answer 818 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Jason
Top achievements
Rank 1
Jason asked on 09 Apr 2021, 09:25 PM

I have been racking my brains on this.  I am using Gridview with a CollectionView.  All fields are strings but they often contain numbers.  For example, "doctor1_21".  The problem is, the default sorting is not natural sorting. I followed your "Custom Sorting handling Sorting Event" example but can't seem to get it working with the CollectionView. I have six columns that are all strings and any of them should be able to sort naturally.  In a perfect word, I could tell the grid or collectionview to use a custom generic IComparerinst using this dllimport and just plug it in once and any column that is selected would sort ascending and descending using this natural sort.  But I simply cannot get it working.  Could you tell me the best way to implement this?  I have seen some where you have to designate the column name, but I would have to then do that for each column. I will do that if needed, but would be nice to have a more generic method.

 

[SuppressUnmanagedCodeSecurity]
    internal static class SafeNativeMethods
    {
        [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
        public static extern int StrCmpLogicalW(string psz1, string psz2);
    }

1 Answer, 1 is accepted

Sort by
0
Martin Ivanov
Telerik team
answered on 14 Apr 2021, 09:35 AM

Hello Jason,

I've tested the StrCmpLogicalW with a CollectionView and a CustomSort and the sorting works. However, keep in mind that in order to make this work you will need to address a couple of additional settings. Basically, the SortDescriptions of a ListCollectionView are taking precedence over its CustomSort. When you sort using the RadGridView's UI the SortDescriptions of the underlying CollectionView are populated which means that if you use a CustomSort IComparer with the StrCmpLogicalW method, this won't take effect. In order to get the desired functionality, you can subscribe to the Sorting event of RadGridView where you can cancel the default sorting and update the CustomSort according to the new sorting state of the column. Here is an example in code:

private void RadGridView_Sorting(object sender, Telerik.Windows.Controls.GridViewSortingEventArgs e)
{
	e.Cancel = true;
	e.Column.SortingState = e.NewSortingState;
	if (e.NewSortingState != SortingState.None)
	{
		collectionView.CustomSort = new MyNaturalStringComparer(e.NewSortingState == SortingState.Descending); // the constructor parameter determines the sort direction (ascending by default)
	}
	else
	{
		collectionView.CustomSort = null;
	}
}

Also, for this to work properly you will need to set the IsCustomSortingEnabled property of each column to True.

I've attached a small example showing this approach. I hope it helps.

Regards,
Martin Ivanov
Progress Telerik

Тhe web is about to get a bit better! 

The Progress Hack-For-Good Challenge has started. Learn how to enter and make the web a worthier place: https://progress-worthyweb.devpost.com.

Jason
Top achievements
Rank 1
commented on 11 May 2021, 06:57 PM

Thank you so much!
Jason
Top achievements
Rank 1
commented on 17 May 2021, 10:12 PM

Hey, one follow-up question on this.  It works perfectly!  But lets say I have 3-4 columns that all need naturalsorting?  How could I make this generic enough to use any column without having to create a new method for each column?
Martin Ivanov
Telerik team
commented on 19 May 2021, 10:48 AM

The first thing that I can suggest is to determine if the custom sort should happen or not in the Sorting event handler. To do so, you can check if the column's DataType is string. For example:

 if (e.Column is GridViewDataColumn && ((GridViewDataColumn)e.Column).DataType == typeof(string))
{
}

The other thing is that you will probably want to sort by a different property based on the clicked column header. In this case, you can consider passing the corresponding property name to the IComparer implementation class when initializing it. And then use a reflection or an if-else/switch statement to get the corresponding values from the compared objects in the Compare() method of the class.

Also, note that the RadGridView control supports multiple columns sort by holding the Shift key which will make the sorting quite complex if you decide to support this scenario. In this situation, you will need to apply sorting per each selected column in the Compare() method's implementation.

Tags
GridView
Asked by
Jason
Top achievements
Rank 1
Answers by
Martin Ivanov
Telerik team
Share this question
or