WPF DataGrid默认排序不起作用

Pro*_*ofK 6 wpf xaml datagrid mvvm wpfdatagrid

我有一个DataGrid,列XAML如下:

<DataGridTextColumn Header="Time" Binding="{Binding Date, StringFormat='yyyy-MM-dd  HH:mm:ss'}" SortMemberPath="Date" SortDirection="Descending" Width="130" CanUserResize="True" />
<DataGridTextColumn Header="Level" Binding="{Binding Level}" Width="60" CanUserResize="True" />
<DataGridTextColumn Header="Source" Binding="{Binding Logger}" Width="150" CanUserResize="True" />
<DataGridTextColumn Header="Message" Binding="{Binding Message}" Width="*" CanUserResize="True" />
Run Code Online (Sandbox Code Playgroud)

我把它绑定到一个ObservableCollection<EalsLogEvent>,EalsLogEvent.Date输入的地方DateTime:

public ObservableCollection<EalsLogEvent> LogEvents 
{
    get
    {
        return _logEvents;
    }
}
Run Code Online (Sandbox Code Playgroud)

网格视图模型使用计时器来刷新自身,除了第一次加载时,在应用程序启动时,网格上的一切似乎都很好.然后,该Time列似乎按降序排序,但按升序排序.

要获得正确的排序,我必须单击列标题两次; 第一次将订单更改为升序,现在匹配列的内容.第二次单击列标题会将其排序顺序更改为降序,这次它会正确排序列内容,即降序.

如果我_logEvents在刷新时使用LINQ对集合进行排序,则会丢失用户通过单击其标题为该列设置的任何顺序.如果我必须让视图告诉模型LINQ排序应该使用哪个顺序,那么有些东西闻起来很糟糕.

dym*_*oid 13

您可以CollectionViewSource在XAML中使用a 来定义默认排序.

假设我们有一个视图模型:

public class ViewModel : INotifyPropertyChanged
{
    public ObservableCollection<Item> Items { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)

我们可以CollectionViewItems集合创建一个自定义:

<Window xmlns:l="clr-namespace:YourNamespace"
        xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase">
    <Window.DataContext>
        <l:ViewModel/>
    </Window.DataContext>
    <Window.Resources>
        <CollectionViewSource Source="{Binding Items}" x:Key="GridItems">
            <CollectionViewSource.SortDescriptions>
                <scm:SortDescription PropertyName="Date" Direction="Descending"/>
            </CollectionViewSource.SortDescriptions>
        </CollectionViewSource>
    </Window.Resources>
    <DataGrid ItemsSource="{Binding Source={StaticResource GridItems}}" AutoGenerateColumns="False">
        <DataGrid.Columns>                    
            <DataGridTextColumn Header="Time" Binding="{Binding Date, StringFormat='yyyy-MM-dd  HH:mm:ss'}" Width="130" CanUserResize="True" />
            <DataGridTextColumn Header="Level" Binding="{Binding Level}" Width="60" CanUserResize="True" />
            <DataGridTextColumn Header="Source" Binding="{Binding Logger}" Width="150" CanUserResize="True" />
            <DataGridTextColumn Header="Message" Binding="{Binding Message}" Width="*" CanUserResize="True" />
        </DataGrid.Columns>
    </DataGrid>
</Window>
Run Code Online (Sandbox Code Playgroud)

使用此方法,您的基础源集合(Items在此示例中)不会受到影响,排序仅在视图中进行.

正如您可以在MSDN中阅读:

您可以将集合视图视为绑定源集合顶部的图层,允许您基于排序,过滤器和组查询来导航和显示集合,而无需操纵底层源集合本身.如果源集合实现了INotifyCollectionChanged接口,则CollectionChanged事件引发的更改将传播到视图.

您还应注意以下事项:

所有集合都有一个默认的CollectionView.WPF始终绑定到视图而不是集合.如果直接绑定到集合,WPF实际上绑定到该集合的默认视图.

因此,使用CollectionViewSource,您只需为您的收藏定义自定义视图.

  • 好东西,@ ahmanoid!非常感谢.然而,它确实让我很烦恼,我咨询的这么多资源似乎认为行本身上的普通旧`SortMemberPath`和`SortDirection`属性都是必需的.是不是`DataGrid`*假设*在构建它自己的默认`CollectionView`时使用这些XAML属性? (2认同)