WPF DataGrid Header Filesize sort
I'm working with a WPF DataGrid which presents a set of imported files into the program. Everything works fine but I've faced a problem sorting file sizes when the header is clicked!
The normal sorting method cannot differentiate between 12*GB and 12*MB so they appear next to each other and that's exactly what I don开发者_如何学编程't want to happen.
Any idea how to solve this problem?
→ Solved the problem by adding a long column even though sizes may look meaningless I had no choice!
First you need an IComparer<string>
that does the sorting taking into account the suffix. I'm sure you can write your own but here's a quick-and-dirty approach that just handles the cases you listed:
public class FileSizeComparer : IComparer<string>
{
public int Compare(string x, string y)
{
var xFields = x.Split('*');
var yFields = y.Split('*');
if (xFields[1] == "GB" && yFields[0] == "MB") return 1;
if (xFields[1] == "MB" && yFields[0] == "GB") return -1;
return int.Parse(yFields[0]) - int.Parse(xFields[0]);
}
}
This can be made a lot more efficient if you are sorting many thousands of rows.
Then you need to hook your comparer into the DataGrid
. The following Stack Overflow answer explains it perfectly:
- How can I apply a custom sort rule to a WPF DataGrid?
You just hook the DataGrid.Sorting
event and wire up your comparer to the ListCollectionView
for your column.
I don't think so that normal string sorting will work in this case. You would have to implement custom sorting.
Check this link for how to implement a custom sort in DataGrid. It also boost sorting performance in a DataGrid.
you would have to handle sorting event of DataGrid.
dataGrid.Sorting += new DataGridSortingEventHandler(SortHandler);
Then inside the event handler you would do something like this (taken from here)
void SortHandler(object sender, DataGridSortingEventArgs e)
{
DataGridColumn column = e.Column;
IComparer comparer = null;
//i do some custom checking based on column to get the right comparer
//i have different comparers for different columns. I also handle the sort direction
//in my comparer
// prevent the built-in sort from sorting
e.Handled = true;
ListSortDirection direction = (column.SortDirection != ListSortDirection.Ascending) ? ListSortDirection.Ascending : ListSortDirection.Descending;
//set the sort order on the column
column.SortDirection = direction;
//use a ListCollectionView to do the sort.
ListCollectionView lcv = (ListCollectionView)CollectionViewSource.GetDefaultView(this.ItemsSource);
//this is my custom sorter it just derives from IComparer and has a few properties
//you could just apply the comparer but i needed to do a few extra bits and pieces
comparer = new ResultSort(direction);
//apply the sort
lcv.CustomSort = comparer;
}
You might want to try a different approach: instead of formatting the data into the grid as strings, and then facing the string-sorting problem, leave the data as a number and use a custom column formatting routine to render the size with MB, GB, etc as desired.
Basically you'll need to derive a class from IValueConverter and let it do the formatting (don't worry about the 'ConvertBack' method; it'll never be called).
In my experience, storing non-string data as strings is almost always the wrong thing to do, for precisely this sort of reason. It's better to leave it as whatever type of data it really is, and find a way to format it "at the last minute".
精彩评论