WPF4 数据表格不会根据列标题排序。

15

我正在尝试使用MVVM设计模式实现我的第一个WPF应用程序。

我创建了一个绑定到ObservableCollection<>的应用程序。应用程序渲染正常,但我希望当我点击列标题时,数据表格能够重新排序行。

我研究了一些帖子,其中提到: 数据源必须实现IEnumerable,我的确实现了。 我需要设置CanUserSortColumns和/或CanUserSort(在每个列上),我已经设置了。 我可以通过指定Sorting回调函数来实现自定义排序,我也这样做了。

但是这些似乎都没有起作用。在调试器中,我的_customerGrid_Sorting函数从未被调用,点击列标题也没有任何效果。

我是否在下面的XAML代码中漏掉了什么?还有其他的接口我需要实现吗?我感到非常迷茫,所以非常感谢任何帮助。

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个回答

27

问题在于这段代码

<DataGridTemplateColumn Header="Cust ID" MinWidth="90" CanUserSort="True" >
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Label Content="{Binding Path=CustID}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
默认排序仅适用于DataGridTextColumn、DataGridComboBoxColumn等类型的列。现在,由于您已定义了DataTemplate和其中的Label,因此该网格不知道如何进行排序。其他人可能会在DataTemplate内定义SstackTemplate等。因此,DataGrid将无法对其进行排序。
我将尽快向您展示一个示例代码,以说明我们可以为此类DataGridTemplateColumn做些什么。但希望我给出的方向能对您有所帮助!
看起来答案非常简单。我使用MVVM对一个样本DataGrid进行了尝试,但我认为我的解决方案也适用于您的情况。
下面的DataGridTemplateColumn中一切都正常,但是您缺少一个非常重要的属性,称为SortMemberPath。WPF需要知道应根据哪个属性进行排序。
 <DataGridTemplateColumn Header="Name" MinWidth="300" CanUserSort="True" Width="*">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Label Content="{Binding Path=Name}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
  </DataGridTemplateColumn>


我不知道你的数据结构。但是修改后的数据结构应该长这样

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

希望它能对你有所帮助!!如果没有帮助到你,请告诉我,我会尝试在某个博客中发布我的应用程序(尽管我很懒!)


谢谢您,大师。这有点帮助。至少我知道为什么默认的排序行为不起作用了。我想这意味着我需要实现自定义排序。我原以为可以通过在DataGrid的Sorting属性中指定处理程序来实现。但我的处理程序没有触发。期待收到您的代码示例,以便给我更多方向。 - Paul Chavez
1
@Paul - 我想你只是遗漏了一个名为“SortMemberPath”的属性。希望能帮到你! - Gurucharan Balakuntla Maheshku
太棒了,大师!谢谢您的帮助!我会通过在DataGridTemplateColumn上指定SortMemberPath="CustID"(例如)来消除DataGrid上的Sorting属性,并删除我的IComparer自定义实现。您的答案将有助于其他人。如果有人对解决方案有疑问,我会尽力帮助他们。 - Paul Chavez
谢谢!这节省了我很多时间。我必须为需要文本换行的行实现CellTemplates,而且我实际上认为您无法对这些列进行排序,但现在我知道您可以! - geekinit
我有一个类似的问题,但是当我用BindingList<T>替换底层集合时,我的DataGrid停止了排序。 - Martin Lottering

-1

试试这个: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>

你的答案和被接受的答案有什么不同?SortMemberPath 的值应该是数据源中列的名称。"Complete" 不是我的成员列之一。 - Paul Chavez
我没有看到上面的答案,可能是他/她在我编辑时发布的。关于标题名称,我在我的wpf测试中尝试了它,如果它有效,你只需要更改标题名称。 - Doro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接