One of the problems with the SPGridView occurs, if you display e.g. the file size of files, and try to sort with this information. The internal value you get from a SPFile of FileInfo Object shows you the length of the file in bytes. This is great if you want to sort this column. But what if you choose to display the long value with the amount of bytes for a file not as the value, but formatted with SPUtility.FormatSize(file.length)?
Well, you cannot sort for this column anymore, because sorting System.string values is not the same as sorting the original file size which is a System.long.
So what can you do to a) format the file size nicely and b) still be able to sort your entries with their file sizes?
- Create a new class with a custom format method
- Add a DataColumn to your DataTable
_DataTable.Columns.Add("Size", typeof(FileSize));
- Create a BoundField and add it to your SPGridView
- Add a new DataRow to your DataTable
row["Size"] = new FileSize(file.Length);
If you look at my FileSize class you will notice that I am overriding the .ToString() method with a PadLeft. This is due to the fact that a string sorting is not the same as sorting a long. But if you put zeros in front of the long and then sort the resulting string, you will get the desired sorting.
The big TODO with this solution is, that you have to disable the filtering for the "Size" column. This is due to the fact that we use our own class in the DataTable, which does not work with the FilteredDataSourcePropertyFormat = "{1} LIKE '{0}'" from the SPGridView, because it is not a string. "System.Data.EvaluateException: Cannot perform 'Like' operation on RH.FileLink and System.String"
new class
1: class FileSize : IFormattable
3: private readonly long _Value;
7: get { return _Value; }
10: public FileSize(long value)
15: public override string ToString()
17: //fill trailing zeros to be able to sort the size correctly
18: string value = _Value.ToString().PadLeft(12);
22: // Write a custom Format method which shows the filesize "nicely"
23: public string ToString(string format, IFormatProvider fp)
25: if (format.Equals("nice"))
26: return SPUtility.FormatSize(_Value);
28: return _Value.ToString(format, fp);
BoundField
1: BoundField size = new BoundField();
2: size.DataField = "Size";
3: size.HtmlEncode = false;
4: size.HeaderText = "Size";
5: size.SortExpression = "Size";
6: // use custom formatting, to display 1Kb instead of 1024
7: size.DataFormatString = "{0:nice}"; 8:
9: _GridView.Columns.Add(size);
Update 24. March 2009
Filtering can be adjusted by changing the "FilteredDataSourcePropertyFormat" property to "{1}='{0}'";