public class Alpha
{
public ObservableCollection<Beta> Items { get; set; }
public Alpha()
{
Items = new ObservableCollection<Beta>();
}
public void DoSomething()
{
Items = GetNewItems(); // whenever I do this, Items gets a new referene,
// so every WPF binding (e.g. datagrids) are broken
}
public ObservableCollection<Beta> GetNewItems()
{
var ret = new ObservableCollection<Beta>();
// some logic for getting some items from somewhere, and populating ret
return ret;
}
}
如何将Items
的整个内容替换为GetNewItems()
的返回值,而不是:
打破绑定。
必须遍历这些项目并将它们逐个复制到另一个集合中吗?
答案 0 :(得分:7)
你有一些选择:
BindingOperations.EnableCollectionSynchronization
一起修改它。 <强>推荐强>
关于您的问题,数字2和3转换为清除现有项目(Clear()),然后添加(Add())您想要的任何方法返回的项目 - 请参阅#3的示例。关键是清算和所有添加必须使用Dispatcher(2)或通过调用BindingOperations.EnableCollectionSynchronization
来完成。
祝你好运!
答案 1 :(得分:3)
你也可以创建自己的类来扩展ObservableCollection,这里有一个通知排序的例子:
https://github.com/jamesmontemagno/mvvm-helpers/blob/master/MvvmHelpers/ObservableRangeCollection.cs
我正在使用上面更简单的实现(我还没有比较通知方面):
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using BaseLibrary.Properties;
namespace BaseLibrary
{
/// <summary>
/// Represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed.
/// </summary>
/// <typeparam name="T"></typeparam>
public class ObservableCollectionEx<T> : ObservableCollection<T>
{
//INotifyPropertyChanged interited from ObservableCollection<T>
#region INotifyPropertyChanged
protected override event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
public void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion INotifyPropertyChanged
/// <summary>
/// Adds the elements of the specified collection to the end of the ObservableCollection(Of T).
/// </summary>
public void AddRange(IEnumerable<T> collection)
{
if (collection == null) throw new ArgumentNullException(nameof(collection));
foreach (var i in collection) Items.Add(i);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
/// <summary>
/// Removes the first occurence of each item in the specified collection from ObservableCollection(Of T).
/// </summary>
public void RemoveRange(IEnumerable<T> collection)
{
if (collection == null) throw new ArgumentNullException(nameof(collection));
foreach (var i in collection) Items.Remove(i);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
/// <summary>
/// Clears the current collection and replaces it with the specified item.
/// </summary>
public void Replace(T item)
{
Replace(new T[] { item });
}
/// <summary>
/// Replaces all elements in existing collection with specified collection of the ObservableCollection(Of T).
/// </summary>
public void Replace(IEnumerable<T> collection)
{
if (collection == null) throw new ArgumentNullException(nameof(collection));
Items.Clear();
foreach (var i in collection) Items.Add(i);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
/// <summary>
/// Initializes a new instance of the System.Collections.ObjectModel.ObservableCollection(Of T) class.
/// </summary>
public ObservableCollectionEx()
: base() { }
/// <summary>
/// Initializes a new instance of the System.Collections.ObjectModel.ObservableCollection(Of T) class that contains elements copied from the specified collection.
/// </summary>
/// <param name="collection">collection: The collection from which the elements are copied.</param>
/// <exception cref="System.ArgumentNullException">The collection parameter cannot be null.</exception>
public ObservableCollectionEx(IEnumerable<T> collection)
: base(collection) { }
}
}
答案 2 :(得分:1)
ObservableCollection实现了INotifyCollectionChanged,它将在添加或删除项目时更新绑定。这里需要的只是清除要触发的CollectionChanged事件的列表。
public void GetNewItems()
{
Items.Clear();
// some logic for getting some items from somewhere, and populating ret
}