2
votes

Firstly let me clarify (if the title wasn't clear enough): I'm discussing System.Windows.Controls.DataGrid from the .NET 4.0 Framework, not the toolkit edition.

I'm currently building up a small re-usable set of classes/view models/etc in my project to build a rather powerfull DataGrid for my application.

Now, by default given an IEnumarable<> ItemsSource the DataGrid control supports header-clicking column sorting.

However, my implementation now uses a CollectionViewSource and ICollectionView to expose data members to the DataGrid. When hooked up in this fashion it seems to rely on the SortDescriptions to sort.

While I like having control from code (could be hooked into all sorts of things) I also require the ability for my users to click the header bars to sort thier results. I'm looking for a way to hook the header-bar clicks to signal my code to adjust the CollectionViewSource appropriately.

  1. Am I going to have to re-style the header buttons to do fire the events?
  2. Is there a way to hook the sort events from the DataGrid control's existing headers?
  3. What is the best way to go about this?
  4. Am I using ICollectionView incorrectly?
3

3 Answers

4
votes

You can handle the DataGrid.Sorting event, use its EventArgs' "e.Column" property to get information about the clicked column header, and also set "e.Handled=true" to prevent the DataGrid's default sorting to kick in. Below is a little example that demonstrates this:

XAML:

<Window x:Class="StackOverflow.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:StackOverflow"
        Title="MainWindow" Height="350" Width="525">
    <DataGrid x:Name="DataGrid" Sorting="DataGrid_Sorting" CanUserAddRows="False">

        <DataGrid.GroupStyle>
            <GroupStyle>
                <GroupStyle.HeaderTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Name}"/>
                    </DataTemplate>
                </GroupStyle.HeaderTemplate>
            </GroupStyle>
        </DataGrid.GroupStyle>

        <DataGrid.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Name}"/>
            </DataTemplate>
        </DataGrid.ItemTemplate>
    </DataGrid>
</Window>

Code-Behind:

using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.ComponentModel;

namespace StackOverflow
{
    public partial class MainWindow : Window
    {
        ListCollectionView lcv;
        public MainWindow()
        {
            InitializeComponent();

            List<Item> items = new List<Item>();
            items.Add(new Item() { Name = "Item1", Category = "A" });

            items.Add(new Item() { Name = "Item5", Category = "B" });
            items.Add(new Item() { Name = "Item3", Category = "A" });
            items.Add(new Item() { Name = "Item4", Category = "B" });
            items.Add(new Item() { Name = "Item2", Category = "A" });

            lcv = new ListCollectionView(items);
            lcv.GroupDescriptions.Add(new PropertyGroupDescription("Category"));

            this.DataGrid.ItemsSource = lcv;

        }

        public class Item
        {
            public string Name { get; set; }
            public string Category { get; set; }
        }

        private void DataGrid_Sorting(object sender, DataGridSortingEventArgs e)
        {            
            e.Handled = true;
            lcv.SortDescriptions.Add(new SortDescription(e.Column.SortMemberPath, ListSortDirection.Ascending));
        }
    }
}
1
votes

Actually I found the answer. A complete blunder on my part. It stemmed from settings on the Columns in the DataGrid Control.

Had to make sure that CanUserSort="True" was set on the DataGridColumn, and that the SortMemberPath property was set.

Example:

            <DataGridTemplateColumn Header="Account #" Width="Auto" CanUserSort="True" SortMemberPath="AccountNum">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding AccountNum}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
-1
votes

Are you able to set the ItemSource to an ObservableCollection<>? Then, the DataGrid will automatically allow sorting when the user user clicks on a column header.