gpt4 book ai didi

wpf - ObservableCollection 不对新添加的项目进行排序

转载 作者:行者123 更新时间:2023-12-04 13:23:08 25 4
gpt4 key购买 nike

我有以下绑定(bind)到 DataGrid 的 ObservableCollection:

public ObservableCollection<Message> Messages = new ObservableCollection<Message>;

XAML:

<DataGrid ItemsSource="{Binding Path=Messages}">

我在启动时使用默认 View 对其进行排序:

ICollectionView view = CollectionViewSource.GetDefaultView(Messages);
view.SortDescriptions.Add(new SortDescription("TimeSent", ListSortDirection.Descending));

一切正常,但问题是每当我向 Messages 集合添加新消息时,它只是附加到列表的底部,而不是自动排序。

Messages.Add(message);

我做错了什么吗?我确信我可以通过每次添加项目时刷新 View 来解决这个问题,但这似乎是错误的做法(更不用说性能方面了)。

最佳答案

所以我做了更多的调查,结果我的问题是由于 WPF 数据网格的限制。当基础数据发生变化时,它不会自动重新排序集合。换句话说,当你第一次添加你的项目时,它会被排序并放置在正确的位置,但如果你改变了项目的属性,它就不会重新排序。 INotifyPropertyChanged 与排序更新无关。它只处理更新显示的数据,但不会触发排序。强制重新排序的是 CollectionChanged 事件,但修改集合中已有的项目不会触发此特定事件,因此不会执行排序。

这是另一个类似的问题: C# WPF Datagrid doesn't dynamically sort on data update

该用户的解决方案是手动调用 OnCollectionChanged()。

最后,我结合了这两个线程的答案:

  1. ObservableCollection not noticing when Item in it changes (even with INotifyPropertyChanged)
  2. ObservableCollection and Item PropertyChanged

我还添加了“智能”排序,如果属性更改是当前在 SortDescription 中使用的值,则仅调用 OnCollectionChanged()。

    public class MessageCollection : ObservableCollection<Message>
{
ICollectionView _view;

public MessageCollection()
{
_view = CollectionViewSource.GetDefaultView(this);
}

public void Sort(string propertyName, ListSortDirection sortDirection)
{
_view.SortDescriptions.Clear();
_view.SortDescriptions.Add(new SortDescription(propertyName, sortDirection));
}

protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
this.AddPropertyChanged(e.NewItems);
break;

case NotifyCollectionChangedAction.Remove:
this.RemovePropertyChanged(e.OldItems);
break;

case NotifyCollectionChangedAction.Replace:
case NotifyCollectionChangedAction.Reset:
this.RemovePropertyChanged(e.OldItems);
this.AddPropertyChanged(e.NewItems);
break;
}

base.OnCollectionChanged(e);
}

private void AddPropertyChanged(IEnumerable items)
{
if (items != null)
{
foreach (var obj in items.OfType<INotifyPropertyChanged>())
{
obj.PropertyChanged += OnItemPropertyChanged;
}
}
}

private void RemovePropertyChanged(IEnumerable items)
{
if (items != null)
{
foreach (var obj in items.OfType<INotifyPropertyChanged>())
{
obj.PropertyChanged -= OnItemPropertyChanged;
}
}
}

private void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e)
{
bool sortedPropertyChanged = false;
foreach (SortDescription sortDescription in _view.SortDescriptions)
{
if (sortDescription.PropertyName == e.PropertyName)
sortedPropertyChanged = true;
}

if (sortedPropertyChanged)
{
NotifyCollectionChangedEventArgs arg = new NotifyCollectionChangedEventArgs(
NotifyCollectionChangedAction.Replace, sender, sender, this.Items.IndexOf((Message)sender));

OnCollectionChanged(arg);
}
}

关于wpf - ObservableCollection 不对新添加的项目进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21197352/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com