对于我的WPF项目,我需要一个始终保持正确顺序的可观察集合。我的想法是使用SortedSet<T>
并实施我自己的AddAndNotify
和RemoveAndNotify
方法。在其中,我会打电话给NotifyPropertyChanged
,就像这样:
public class ObservableSortedSet<T> : SortedSet<T>, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
public void AddAndNotify(T element)
{
Add(element);
NotifyPropertyChanged(...);
}
public void RemoveAndNotify(T element)
{
Remove(element);
NotifyPropertyChanged(...);
}
}
但是那个属性(或属性)会是什么?
如何在集合内容发生变化时实现一个告诉UI更新的集合?
或者在ViewModel中直接使用SortedSet是否有更简单的方法?
编辑:
我不想将预定义的ObservableCollection
与排序视图一起使用。我知道这可以使用CollectionViewSource
或转换器,但这些解决方案对我没有吸引力。我有CollectionViewSource
不起作用的层次结构数据,我认为转换器版本是CollectionViewSource
限制的可怕解决方法。我想使用一个干净的解决方案。
所以这个问题不是how to sort ObservableCollection的重复。我不想对ObservableCollection
进行排序,我想使用可以告知用户界面更改的SortedSet
。
答案 0 :(得分:5)
您应该实现INotifyCollectionChanged Interface。
About
答案 1 :(得分:3)
我设法这样做了:
public class ObservableSortedSet<T> : SortedSet<T>, INotifyCollectionChanged where T : IComparable<T>
{
public event NotifyCollectionChangedEventHandler CollectionChanged;
public new void Add(T element)
{
base.Add(element);
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
public override void Clear()
{
base.Clear();
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
public new void Remove(T element)
{
base.Remove(element);
CollectionChanged?.Invoke(this,
new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
为什么我总是将Reset
操作作为EventArg?
Remove
的原因:如果集合没有索引(请参阅Implementing INotifyCollectionChanged on a collection without indexes或Observable Stack and Queue - 似乎无法使用 - 在这两种情况下,归结为无法指定正确的索引,导致运行时错误。请查看答案下方的所有评论“索引xyz对我不起作用!”。)
Add
的原因:在内部,集合IS已排序,但UI未正确反映此情况。我的猜测是,通过提供EventArg new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, element);
,GUI只会被告知新元素应该添加到结尾。
根据https://msdn.microsoft.com/en-us/library/system.collections.specialized.notifycollectionchangedaction(v=vs.100).aspx,Reset
代表“收藏内容发生了巨大变化”。这对SortedSet
来说是正确的,因为如果只添加或删除一个元素,其内部结构可能会发生很大变化。所以也许我的解决方案甚至不是一种解决方法(即使它感觉就像一个)!
答案 2 :(得分:0)
您可以使用CollectionViewSource:
<td class="text-center">
<?php
$url=get_curl_content_tx("http://example.com/". $order->order_id);
$arr = json_decode($url, true);
if (is_array($arr['data']) || is_object($arr['data'])) {
foreach($arr['data'] as $data ) {
$match = false;
if ($data['amount'] == $order->amount) {
$match = $data;
break;
}
}
if($match !== false ) {
if( .. ) {
// do something
}
else {
// do something else
}
}
else { }
}
?>
</td>
然后,按照您需要的属性对其进行排序:
<Window.Resources>
<CollectionViewSource x:Key="yourViewSource" source="{Binding YourCollection}"/>
</Window.Resources>
将其绑定为ItemSource:
CollectionViewSource yourViewSource=
((CollectionViewSource)(this.FindResource("yourViewSource")));
yourViewSource.SortDescriptions.Add(new SortDescription("SortByProperty", ListSortDirection.Descending));