ListView Sorting

This sample shows how to create a ListView control that uses a GridView to display a list of dates that are defined as DateTime objects. The sample enables sorting of data in ascending or descending order according to the contents of one column.

Key Step 1. Add Sorting method in GridViewColumnHeader.Click event. Consider both last clicked header and last sorting direction, and decide current sorting direction. Sorting itself is very simple, as written in Sort method.

 

ListView x:Name='lv' GridViewColumnHeader.Click="GridViewColumnHeaderClickedHandler">

 

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 != _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)

        {

            lv.Items.SortDescriptions.Clear();

            SortDescription sd = new SortDescription(sortBy, direction);

            lv.Items.SortDescriptions.Add(sd);

            lv.Items.Refresh();

        }

Key Step 2(optional). In order to figure out current sorting status, add Template in the Column Header. Change Template along with sorting status, so it should also be added in GridViewColumnHeader.Click event. And in the Template, Use path to draw the arrows.

  <DataTemplate x:Key="HeaderTemplateArrowUp">

      <DockPanel>

        <TextBlock HorizontalAlignment="Center" Text="{Binding}"/>

        <Path x:Name="arrow"

           StrokeThickness = "1"

           Fill            = "gray"

           Data            = "M 5,10 L 15,10 L 10,5 L 5,10"/>

     </DockPanel>

    </DataTemplate>

    <DataTemplate x:Key="HeaderTemplateArrowDown">

      <DockPanel>

        <TextBlock HorizontalAlignment="Center" Text="{Binding }"/>

        <Path x:Name="arrow"

              StrokeThickness = "1"

              Fill            = "gray"

              Data            = "M 5,5 L 10,10 L 15,5 L 5,5"/>

      </DockPanel>

    </DataTemplate>

 

  void GridViewColumnHeaderClickedHandler(object sender, RoutedEventArgs e)

        {

           

            if (headerClicked != null)

            {

                if (_lastHeaderClicked != null)

                {

                    _lastHeaderClicked.Column.HeaderTemplate = null;

                }

           

                if (direction == ListSortDirection.Ascending)

                {

                    headerClicked.Column.HeaderTemplate =

                      Resources["HeaderTemplateArrowUp"] as DataTemplate;

                }

                else

                {

                    headerClicked.Column.HeaderTemplate =

                      Resources["HeaderTemplateArrowDown"] as DataTemplate;

                }

               

            }

        }

 

Key Step 3. Put it all together and you have the following ListView sorting!

This sample is based on the February CTP.

 

Declaimer: This posting is provided "AS IS" with no warranties, and confers no rights.

ListViewSorting.zip

Comments

  • Anonymous
    March 18, 2006
    Dear all,

    My scenario is my listView is bind to DataTable
    and I use BindingListCollectionView to filter data. This is my code:

    // Binding data to ListView
    listViewCustomer.DataContext = _orderTransactionDetailBC.OTDataSet.CompanyList;

    BindingListCollectionView view = (BindingListCollectionView)CollectionViewSource.GetDefaultView(_orderTransactionDetailBC.OTDataSet.CompanyList);

    // Make filtering
    view.CustomFilter = "DeleteFlag = 0";
    view.Refresh();

    My problem is when I remove one or more rows in DataTable, listview remove these rows immediately but it still more focus. And then I remove only one row next times, listview remove more rows. I really don't know why ?

    Please help me.
    Thanks
  • Anonymous
    May 04, 2006
    I'm missing something: for me, ListView does not offer the property 'GridViewColumnHeader.Click'.

    I am using Feb CTP, though. Funny.
  • Anonymous
    May 07, 2006
    Hello, Radeldudel

    GridViewColumnHeader is derived from ButtonBase and it should have click event. Please double-check the version you used and downloade the source code. If it doesn't work for you, please paste the error info here. We will help you out.

    Thanks.
  • Anonymous
    September 18, 2006
    Hi, Everything works fine until I change the GridViewColumn Header="Client Name", then I will receive runtime error "System.InvalidOperationException: "Failed to compare two elements in the array."  Is there any trick that will allow the header use mulitple words?

    Thank you.
  • Anonymous
    September 18, 2006
    Hi, everything works fine until I change the <GridViewColumn Header = "Two Words" ...>. And I received runtime error -- System.InvalidOperationException: "Failed to compare two elements in the array.".  Is there any alternative way around it.  I check the forum http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=392037&SiteID=1.  But I don't understand how the converter will help on the content of the header.  Thanks.
  • Anonymous
    December 29, 2006
    I recently downloaded the VS2005 add-ons for WinFX. I have been playing around with Avalon/WFP/WinFX/XAML (What the heck is the real name anyway?) trying to learn how it works. When I try this example it tells me that "GridViewColumnHeader.Click" doesn't exist.I downloaded the samples most of them won't display properly in VS2005. They seem to compile and run, but the design view reports some sort of error.It looks like WinFX is "Released" but there seem to be a lot of issues. Should I wait until another version to begin writing XBAP apps or is it ok to use this in a production environment?Thanks,Eric
  • Anonymous
    January 09, 2007
    The design experience still requires work. We are hoping to have a much better experience when the next version of Visual Studio ships this year.
  • Anonymous
    July 26, 2007
    PingBack from http://ligao101.wordpress.com/2007/07/27/customizing-listview-in-wpf-part-i/