Best way to make WPF ListView/GridView sort on column-header clicking?

前端 未结 10 1140
感动是毒
感动是毒 2020-11-29 17:12

There are lots of solutions on the internet attempting to fill this seemingly very-basic omission from WPF. I\'m really confused as to what would be the \"best\" wa

10条回答
  •  旧巷少年郎
    2020-11-29 18:07

    MSDN has an easy way to perform sorting on columns with up/down glyphs. The example isn't complete, though - they don't explain how to use the data templates for the glyphs. Below is what I got to work with my ListView. This works on .Net 4.

    In your ListView, you have to specify an event handler to fire for a click on the GridViewColumnHeader. My ListView looks like this:

    
        
            
                
                    
                        
                    
                
                
                    
                        
                    
                
            
        
    
    

    In your code behind, set up the code to handle the sorting:

    // Global objects
    BindingListCollectionView blcv;
    GridViewColumnHeader _lastHeaderClicked = null;
    ListSortDirection _lastDirection = ListSortDirection.Ascending;
    
    // Header click event
    void results_Click(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);
    
            if (direction == ListSortDirection.Ascending)
            {
                headerClicked.Column.HeaderTemplate =
                  Resources["HeaderTemplateArrowUp"] as DataTemplate;
            }
            else
            {
                headerClicked.Column.HeaderTemplate =
                  Resources["HeaderTemplateArrowDown"] as DataTemplate;
            }
    
            // Remove arrow from previously sorted header
            if (_lastHeaderClicked != null && _lastHeaderClicked != headerClicked)
            {
                _lastHeaderClicked.Column.HeaderTemplate = null;
            }
    
            _lastHeaderClicked = headerClicked;
            _lastDirection = direction;
        }
    }
    
    // Sort code
    private void Sort(string sortBy, ListSortDirection direction)
    {
        blcv.SortDescriptions.Clear();
        SortDescription sd = new SortDescription(sortBy, direction);
        blcv.SortDescriptions.Add(sd);
        blcv.Refresh();
    }
    

    And then in your XAML, you need to add two DataTemplates that you specified in the sorting method:

    
        
            
            
        
    
    
    
        
            
            
        
    
    

    Using the DockPanel with LastChildFill set to true will keep the glyph on the right of the header and let the label fill the rest of the space. I bound the DockPanel width to the ActualWidth of the GridViewColumnHeader because my columns have no width, which lets them autofit to the content. I did set MinWidths on the columns, though, so that the glyph doesn't cover up the column title. The TextBlock Text is set to an empty binding which displays the column name specified in the header.

提交回复
热议问题