15
votes

I am trying to implement my first WPF application using an MVVM design pattern.

I created an application that is databinding to an ObservableCollection<>. The application renders fine, but I expect the datagrid to re-sort the rows when I click on the column headers.

I've researched posts that said: The data source has to implement IEnumerable, mine does. I need to set CanUserSortColumns and/or CanUserSort (on each column), I did. I could implement a custom sort by specifying the Sorting callback function, I did.

None of these seem to have helped. In the debugger, my _customerGrid_Sorting function never gets called and clicking on the column headers has no effect.

Am I missing something in the XAML that follows? Is there another interface I need to implement? I am feeling very lost right now, so any help is appreciated.

XAML:

        <DataGrid Name="_customerGrid" 
            AutoGenerateColumns="False" 
            CanUserSortColumns="True"
            ColumnHeaderStyle="{StaticResource columnHeaderStyle}"
            HorizontalAlignment="Left" 
            ItemsSource="{Binding Path=AllCustomers}" 
            RowDetailsVisibilityMode="VisibleWhenSelected"
            RowStyle="{StaticResource DataGridRowStyle}"
            SelectionUnit="FullRow"
            Sorting="_customerGrid_Sorting"
            VerticalAlignment="Top">
            <DataGrid.Columns>
                <DataGridTemplateColumn Header="Cust ID" MinWidth="90" CanUserSort="True" >
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Label Content="{Binding Path=CustID}" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTemplateColumn Header="Name" MinWidth="300" CanUserSort="True" Width="*">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Label Content="{Binding Path=Name}" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
2

2 Answers

27
votes

The problem is this code

<DataGridTemplateColumn Header="Cust ID" MinWidth="90" CanUserSort="True" >
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Label Content="{Binding Path=CustID}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>

The default sorting works as stated everywhere only for DataGridTextColumn, DataGridComboBoxColumn,etc.

Now here the grid does not know how to sort because you have defined a DataTemplate and a Label inside it. Some other person might have defines a SstackTemplate, etc inside DataTemplate. So the DataGrid will not know how to sort it.

I will try to post you a sample code very soon as what we can do for such DataGridTemplateColumn. But hope the direction I have given you helps!!


Seems that the answer is very simple. I tried it with a sample DataGrid using MVVM but my solution should work for you i feel

Everything is fine in the below DataGridTemplateColumn but you are missing a very important attribute called SortMemberPath. Thw WPF should know on which property it should sort.

The original one which you posted looks like this

 <DataGridTemplateColumn Header="Name" MinWidth="300" CanUserSort="True" Width="*">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Label Content="{Binding Path=Name}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
  </DataGridTemplateColumn>


I dont know your data structures. But the modified one should look like this

 <DataGridTemplateColumn  SortMemberPath="Name" Header="Name" MinWidth="300" CanUserSort="True" Width="*">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Label Content="{Binding Path=Name}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
  </DataGridTemplateColumn>

I hope it helps you!! Let me know if it does not help you, I will try to post my application in some blog ( I am lazy to do it though !!)

-1
votes

Try this one: SortMemberPath="Complete"

<DataGridTemplateColumn Header="CustID" SortMemberPath="Complete" MinWidth="90"      
CanUserSort="True" CanUserResize="True">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <Label Content="{Binding Path=CustID}"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>