Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF ListView sorting on column click

I have a listview for which the items gets added at run time in form of a grid with single/multiple columns. Now I need to get the sort working. Once the list view has items in it and they click on the column it should sort it on that column.

Below is the code for the listview

<ListView Name="lstValue" Margin="0,0,0,10"></ListView>

C# code where it populates the list view:

 case "Person":
                        dt = GetDataTable(GET_Person)
                        this.lstValue.View = gridview;
                        gridview.Columns.Add(new GridViewColumn { Header = "Number", 
                            DisplayMemberBinding = new Binding("Number") });
                        gridview.Columns.Add(new GridViewColumn { Header = "Name", 
                            DisplayMemberBinding = new Binding("Name") });
                        foreach(DataRow dr in dt.Rows)
                        {
                                                          this.lstValue.Items.Add(new ReportItem { Number = dr["Number"].ToString(),
                                Name = dr["Name"].ToString() });
                        }
                        break;

They should be able to sort on name or number.

like image 500
user565992 Avatar asked Jun 11 '15 17:06

user565992


People also ask

How do I sort items in ListView?

Click the various column headers in the ListView control. When you click the header, the contents of the ListView control are sorted in ascending order based on the column that you click. When you click the same column header again, that column is sorted in descending order.

How do you sort data in GridView by clicking column header in C#?

Start by adding a GridView to your web page. To make the columns sortable, you need to set the GridView's property AllowSorting = “true” and OnSorting = “OnSorting”. SortExpression property will hold the name of the column you want to sort.

What is GridView WPF?

The GridView view mode displays a list of data items by binding data fields to columns and by displaying a column header to identify the field. The default GridView style implements buttons as column headers.


2 Answers

This link is the MSDN way. The main thing is to handle the click on the gridview column header.

<ListView x:Name='lv' Height="150" HorizontalAlignment="Center" 
  VerticalAlignment="Center" 
  GridViewColumnHeader.Click="GridViewColumnHeaderClickedHandler"
 >

And in the code:

GridViewColumnHeader _lastHeaderClicked = null;
ListSortDirection _lastDirection = ListSortDirection.Ascending;

void GridViewColumnHeaderClickedHandler(object sender,RoutedEventArgs e)
{
  GridViewColumnHeader headerClicked = e.OriginalSource as GridViewColumnHeader;
  ListSortDirection direction;

  if (headerClicked != null)
  {
      if (headerClicked.Role != GridViewColumnHeaderRole.Padding)
      {
          if (headerClicked != _lastHeaderClicked)
          {
             direction = ListSortDirection.Ascending;
          }
          else
          {
             if (_lastDirection == ListSortDirection.Ascending)
             {
               direction = ListSortDirection.Descending;
             }
             else
             {
                 direction = ListSortDirection.Ascending;
             }
          }

          string header = headerClicked.Column.Header as string;
          Sort(header, direction);

          _lastHeaderClicked = headerClicked;
          _lastDirection = direction;
       }
    }
  }

 private void Sort(string sortBy, ListSortDirection direction)
 {
  ICollectionView dataView =
    CollectionViewSource.GetDefaultView(lv.ItemsSource);

  dataView.SortDescriptions.Clear();
  SortDescription sd = new SortDescription(sortBy, direction);
  dataView.SortDescriptions.Add(sd);
  dataView.Refresh();

}

Basically that's it. I did not include adding little direction glyphs on the column header to show the direction. If you want to see how to do that you can refer to the full tutorial (see link above).

like image 157
Liz Avatar answered Oct 06 '22 03:10

Liz


It's worth to node that accepted answer assumes the header names are equal to binding paths. Original MSDN takes paths form actual bindings. Here is basically the same code without dozen of redundant if/elses:

private GridViewColumnHeader lastHeaderClicked = null;
private ListSortDirection lastDirection = ListSortDirection.Ascending;

private void onHeaderClick(object sender, RoutedEventArgs e) {
    if (!(e.OriginalSource is GridViewColumnHeader ch)) return;
    var dir = ListSortDirection.Ascending;
    if (ch == lastHeaderClicked && lastDirection == ListSortDirection.Ascending)
        dir = ListSortDirection.Descending;
    sort(ch, dir);
    lastHeaderClicked = ch; lastDirection = dir;
}

private void sort(GridViewColumnHeader ch, ListSortDirection dir) {
    var bn = (ch.Column.DisplayMemberBinding as Binding)?.Path.Path;
    bn = bn ?? ch.Column.Header as string;
    var dv = CollectionViewSource.GetDefaultView(accessList.ItemsSource);
    dv.SortDescriptions.Clear();
    var sd = new SortDescription(bn, dir);
    dv.SortDescriptions.Add(sd);
    dv.Refresh();
}
like image 40
Pawcio Avatar answered Oct 06 '22 04:10

Pawcio