在业务层中拥有List<T>
需要在UI上显示的最佳做法是什么?我目前在viewmodel中使用带有ObservableCollection<T>
的数据绑定,它复制了List<T>
的数据。显而易见的问题是,在业务层中修改List<T>
时,需要重新创建ObservableCollection<T>
,因此List<T>
的更改会反映在UI中。这不是最好的方法。
我也不会接受在业务层中使用ObservableCollection<T>
作为答案。
谢谢!
答案 0 :(得分:7)
如果您坚持让List<T>
和单独的事件通知列表修改,那么复制是唯一明智的方法。
如果您有ListChanged
事件但没有详细说明实际更改的内容,则可以避免重复,只需将列表包装在实现INotifyCollectionChanged
接口的代理集合中,该接口将触发相应的{{ 1 {} CollectionChanged
模式中的事件。
如果您有详细的NotifyCollectionChangedAction.Reset
,ItemChanged
等事件,那么您实际上是在复制ItemAdded
功能。在这种情况下,您可以将应用程序包装在实现ObservableCollection<T>
接口的代理集合中,但它可以理解您的体系结构并将事件转换为适当的INotifyCollectionChanged
。
在业务层中拥有NotifyCollectionChangedAction
根本不是一个坏主意。它是一个专门的集合,提供通知接口来通知项目更改,而不是专门为WinForms或WPF或其他任何设计的类。
答案 1 :(得分:3)
你可以实现INotifyCollectionChanged接口,但是如果你想以一种你可以保留你的实现的方式使用它,那么在实现你自己的类的情况下也可以执行IEnumerable的集合将完成很多工作对于你来说,例如下面的内容,这是我用来保存将要更新的所有集合的基类,在这个实现中,在变量_ordering中还有一个排序考虑因素:
public abstract class BaseINotifyCollectionChanged<T, K> : INotifyCollectionChanged, IEnumerable<T>
{
Func<T, K> _ordering;
bool _ascending;
public BaseINotifyCollectionChanged()
{
}
public BaseINotifyCollectionChanged(Func<T, K> ordering, bool ascending = true)
{
_ordering = ordering;
_ascending = ascending;
OnCollectionChanged();
}
protected abstract IList<T> GetCollection();
public event NotifyCollectionChangedEventHandler CollectionChanged;
protected void OnCollectionChanged()
{
if (CollectionChanged != null)
CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
public void RaiseCollectionChanged()
{
OnCollectionChanged();
}
public IEnumerator<T> GetEnumerator()
{
return _ordering == null ? GetCollection().GetEnumerator() : _ascending ? GetCollection().OrderBy<T, K>(_ordering).GetEnumerator() :
GetCollection().OrderByDescending<T, K>(_ordering).GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return _ordering == null ? GetCollection().GetEnumerator() : _ascending ? GetCollection().OrderBy<T, K>(_ordering).GetEnumerator() :
GetCollection().OrderByDescending<T, K>(_ordering).GetEnumerator();
}
}
}
如果你有这个实现,你可以按照自己的意愿使用,并在你的应用程序中找到你需要的所有收藏,在这里为你自己做一些干是你可以给的一个例子这个抽象类:
public class Categories : BaseINotifyCollectionChanged<Category, string>
{
long _onCategoryRoot;
public void SetOnCategoryRoot(long categoryId)
{
_onCategoryRoot = categoryId;
RaiseCollectionChanged();
}
protected override IList<Category> GetCollection()
{
Category category = new Category();
return _onRoot ? category.GetRootCategories() : category.GetSubCategoriesOnRoot(_onCategoryRoot);
}
}
当您在课程中设置 _onCategoryRoot 时,您将要显示的集合将通过 RaiseCollectionChanged()方法进行更新,因此您需要在viewmodel中添加一个类类别的属性,并在XAML中设置绑定。