views:

31

answers:

1

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>
+1  A: 

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

Guru Charan
Thanks Guru, that helps a little. At least I know why the default sort behavior doesn't work. I take it that means I need to implement a custom sort. Which I thought I could do by specifying a handler in the Sorting attribute of the DataGrid. But my handler doesn't fire. I look forward to receiving your code sample to give me more direction.
Paul Chavez
@Paul - I think you were just missing an attribute called "SortMemberPath". Hope it helps!!
Guru Charan
Great answer Guru! Thank you for your help! I will add that by specifying the SortMemberPath="CustID" (for instance) on the DataGridTemplateColumn, I was able to eliminate the Sorting attribute on the DataGrid and remove my custom implementation of IComparer. I your answer helps others. If anyone has questions about the solution, I'll try to help them.
Paul Chavez