Search code examples
c#.netsortingdatagridviewsortcomparefunction

DataGridView: sort by one type of data first


I have a DataGridView that I populate with a file and folder list. I'd like to sort the DataGridView alphabetically, but with all the folders above the files. Here's the general idea:

.\folder1\
.\folder2\
.\folder3\
.\file1
.\file2

I have a column with icons for the different filetypes, so there's a folder icon and file icons. It's the only difference I have between the two columns. Here's a picture: enter image description here

So you can see that files and folders have different icons. Here is my current sort method:

private void dgvFiles_SortCompare(object sender, DataGridViewSortCompareEventArgs e) {
    if(e.Column.Index == 1) {
        // ???
    }
    else if(e.Column.Index == 4) {
        string cellValue1 = e.CellValue1.ToString(),
        cellValue2 = e.CellValue2.ToString();

        if(!string.IsNullOrWhiteSpace(cellValue1) && !string.IsNullOrWhiteSpace(cellValue2)) {
            cellValue1 = Regex.Replace(cellValue1, "[^.0-9]", "");
            cellValue2 = Regex.Replace(cellValue2, "[^.0-9]", "");

            int a = int.Parse(cellValue1), b = int.Parse(cellValue2);

            e.SortResult = a.CompareTo(b);

            e.Handled = true;
        }
    }
}

Is it possible to sort the DataGridView this way using a custom SortCompare method? If so, how?


Solution

  • So what I did instead was I created a class for folder items named FolderItem. I then created a list of these FolderItem objects and populated the DataGridView using the list. It actually made it really easy--I just had to use this snippet of code:

    List<FolderItem> items = new List<FolderItem>();
    
    private void dgvFiles_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) {
        if(e.ColumnIndex == 1) {
            items.OrderBy(i => i.type).ThenBy(i => i.oldName);
    
            items.Reverse(); // to account for ascending/descending order
    
            RefreshDataGridView();
        }
    }
    
    public void RefreshDataGridView() {
        dgvFiles.Rows.Clear();
    
        foreach(FolderItem item in items) {
            dgvFiles.Rows.Add(item.icon, item.oldName, item.newName, item.type, item.size, item.created, item.modified);
        }
    }
    

    (type was null for folders so it occurred above the other items.)

    You could also probably find some way to bind the datagridview to the list, but I didn't do that.