WPF DataGrid默认排序不起作用

标签 wpf xaml mvvm datagrid 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" />

我将它绑定(bind)到 ObservableCollection<EalsLogEvent> , 其中 EalsLogEvent.Date输入 DateTime :
public ObservableCollection<EalsLogEvent> LogEvents 
{
    get
    {
        return _logEvents;
    }
}

GridView 模型使用计时器来刷新自身,网格看起来一切正常,除了第一次加载时,在应用程序启动时。然后,Time列似乎按降序排序,但按升序排序。

要正确排序,我必须单击列标题两次;第一次将顺序更改为升序,现在与列的内容匹配。第二次单击列标题将其排序顺序更改回降序,这一次它正确地对列内容进行排序,即降序。

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

最佳答案

您可以使用 CollectionViewSource在 XAML 中定义默认排序。

假设我们有一个 View 模型:

public class ViewModel : INotifyPropertyChanged
{
    public ObservableCollection<Item> Items { get; private set; }
}

我们可以创建一个自定义 CollectionView对于Items收藏:
<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>

使用这种方法,您的基础源集合(在此示例中为 Items)不会受到影响,排序仅发生在 View 中。

正如您在 MSDN 中所读到的那样:

You can think of a collection view as the layer on top of the binding source collection that allows you to navigate and display the collection based on sort, filter, and group queries, all without having to manipulate the underlying source collection itself. If the source collection implements the INotifyCollectionChanged interface, the changes raised by the CollectionChanged event are propagated to the views.



您还应该注意以下几点:

All collections have a default CollectionView. WPF always binds to a view rather than a collection. If you bind directly to a collection, WPF actually binds to the default view for that collection.



因此,使用 CollectionViewSource ,您只是为您的收藏定义了一个自定义 View 。

关于WPF DataGrid默认排序不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28985125/

相关文章:

c# - 允许用户通过拖动调整 WPF TreeView 节点的大小

c# - 使用 x :Shared ="False" resources in external assembly in WPF 时出错

c# excel 雷达图 - 如何更改水平轴?

c# Uri 加载不确定?

WPF 应用程序未拾取 Segoe UI 符号字体

wpf - Resource 中的 DataTemplate 将 ViewModel 设置为 View,但随后

android - 在 ViewModel 中观察 LiveData 最佳实践

c# - 绑定(bind)不响应 PropertyChanged

c# - 以编程方式在代码隐藏中添加视觉状态 setter

android - RoboBinding ViewModel如何知道要返回的变量