我有一个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" />
我将其绑定到ObservableCollection<EalsLogEvent>
,其中EalsLogEvent.Date
已键入DateTime
:
public ObservableCollection<EalsLogEvent> LogEvents
{
get
{
return _logEvents;
}
}
网格视图模型使用计时器自行刷新,除了首次加载时,在应用启动时,网格上的一切似乎都很好。然后,Time
列似乎按降序排序,但按升序排序。
要获得正确的排序,我必须单击列标题两次;第一次将订单更改为升序,现在匹配列的内容。第二次单击列标题会将其排序顺序更改为降序,这次它会正确排序列内容,即降序。
如果我在_logEvents
刷新时使用LINQ对集合进行排序,则会丢失用户为该列设置的任何顺序,方法是单击其标题。如果我必须让视图告诉模型LINQ排序应该使用哪种顺序,那就有些闻起来很糟糕。
答案 0 :(得分:12)
您可以在XAML中使用CollectionViewSource
来定义默认排序。
假设我们有一个视图模型:
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
)不会受到影响,排序仅在视图中进行。
您可以阅读MSDN:
您可以将集合视图视为绑定顶部的图层 源集合,允许您导航和显示 基于排序,过滤和组查询的集合,都没有 必须操纵底层的源集合本身。如果 source collection实现了INotifyCollectionChanged接口, CollectionChanged事件引发的更改将传播到 意见。
您还应注意以下事项:
所有集合都有默认的CollectionView。 WPF总是绑定到 查看而不是集合。如果直接绑定到集合, WPF实际上绑定到该集合的默认视图。
因此,使用CollectionViewSource
,您只需为自己的收藏定义自定义视图。