Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I implement automatic sorting of DataGridView?

I am programmatically adding columns to a DataGridView and then binding to a list. By default, the SortMode of the columns are Automatic. But when I run my app, clicking on the headers does nothing. The up/down arrows aren't showing up. From reading MSDN, not much is said about automatic sorting. They go into more detail about programmatic sorting. So, I'm assuming the automatic way should be easy. MSDN goes on to say "Unless column headers are used for selection, clicking the column header automatically sorts the DataGridView by this column and displays a glyph indicating the sort order." What exactly does that mean? Could I be setting a grid property that conflicts with the sorting? What am I missing?

AutoGenerateColumns = false;
AllowUserToAddRows = false;
AllowUserToDeleteRows = false;
AllowUserToResizeRows = false;
AllowUserToResizeColumns = false;
ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
ReadOnly = true;
MultiSelect = false;
RowHeadersVisible = false;
SelectionMode = DataGridViewSelectionMode.FullRowSelect;
CellBorderStyle = DataGridViewCellBorderStyle.None;


    DataGridViewTextBoxColumn idColumn = new DataGridViewTextBoxColumn();
    idColumn.HeaderText = "ID";
    idColumn.DataPropertyName = "IDNumber";

    DataGridViewTextBoxColumn nameColumn = new DataGridViewTextBoxColumn();
    nameColumn.HeaderText = "Name";
    nameColumn.DataPropertyName = "Description";

    DataGridViewTextBoxColumn lastModifiedColumn = new DataGridViewTextBoxColumn();
    lastModifiedColumn.HeaderText = "Last Modified";
    lastModifiedColumn.DataPropertyName = "Date";

    Columns.Add(idColumn);
    Columns.Add(nameColumn);
    Columns.Add(lastModifiedColumn);

    List<IMyObject> bindingList = GetMyList();
    DataSource = bindingList;
like image 891
bsh152s Avatar asked Sep 22 '10 15:09

bsh152s


People also ask

What is the difference between DataGrid and DataGridView?

The DataGrid control is limited to displaying data from an external data source. The DataGridView control, however, can display unbound data stored in the control, data from a bound data source, or bound and unbound data together.

Which is better ListView or DataGridView?

Yes a ListView looks nicer than a DataGrid, but a Datagrid is better because it has more functionality (out of the box that is). With a ListView you cannot: Copy and paste - although you can select a row of data in both controls, you can't copy and paste a whole row from the ListView.

What is DataGridView control?

The DataGridView control provides a powerful and flexible way to display data in a tabular format. You can use the DataGridView control to show read-only views of a small amount of data, or you can scale it to show editable views of very large sets of data.

How do I make DataGrid read-only?

To make a column read-only programmaticallySet the DataGridViewColumn. ReadOnly property to true .


2 Answers

We use BindingListView to bind List<T>s to DataGridViews, and it's worked beautifully for us.

Here is a very simple example of creating a view of a list of objects (in C#):

List<Customer> customers = GetCustomers();
BindingListView<Customer> view = new BindingListView<Customer>(customers);
dataGridView1.DataSource = view;

Check out https://stackoverflow.com/a/17952576/116891 for a lot more details about DGV sorting and databinding.

If you don't want to add something that heavy, you can try this implementation of a SortableBindingList<T> (with updates).

Both give you sorting right out of the box, and BindingListView is even faster than DataViews, according to their benchmarks.

like image 72
Chris Doggett Avatar answered Sep 22 '22 05:09

Chris Doggett


Best solution I've found:

EDIT: Since posting I found this implementation of SortableBindingList(Of T) to be the best solution, with the exception that I modified line 52 to be IEnumerable rather than ICollection, since the constructor is casting anyway and it works.

Alternatively, the solution below needs no custom class:

The DataGridView may be sorted without implementing a custom class. Note that my code is in VB.NET, but it should translate. The data must first be added to the grid.Rows:

For Each item In dataList
    grid.Rows.Add(item.Id, item.Name, item.DateProperty)
Next

Then implement these event handlers. The second one is to ensure that date sorting works. You only need it if your grid will have a sortable date column:

Private Sub grid_ColumnHeaderMouseClick(ByVal sender As Object, ByVal e As DataGridViewCellMouseEventArgs) Handles grid.ColumnHeaderMouseClick
    Dim col = grid.Columns(e.ColumnIndex)
    Dim dir As System.ComponentModel.ListSortDirection

    Select Case col.HeaderCell.SortGlyphDirection
        Case SortOrder.None, SortOrder.Ascending
            dir = System.ComponentModel.ListSortDirection.Ascending
        Case Else
            dir = System.ComponentModel.ListSortDirection.Descending
    End Select

    grid.Sort(col, dir)
End Sub

Private Sub grid_SortCompare(ByVal sender As Object, ByVal e As DataGridViewSortCompareEventArgs) Handles grid.SortCompare
    'This event occurs only when the DataSource property is not set and the VirtualMode property value is false.

    If e.Column.Name = "DateProperty" Then
        e.SortResult = Date.Compare(CType(e.CellValue1, Date), CType(e.CellValue2, Date))

        e.Handled = True
    End If

End Sub

An important thing to note is that only the properties you add to the row are part of the resulting object, since there is no binding. In order to maintain your entire object, you will need to add columns for every property, setting the columns Visible = False for any that should not be displayed.

like image 31
mbomb007 Avatar answered Sep 26 '22 05:09

mbomb007