gpt4 book ai didi

.net - ObservableCollection 更改时重新评估 LINQ 查询

转载 作者:行者123 更新时间:2023-12-03 21:54:49 26 4
gpt4 key购买 nike

我有一个共同的问题,我想(希望)找到一个更好的解决方案来继续前进。我有一个包含数据主列表的 ObservableCollection。在我的客户端代码中,我需要将数据“转换”为新表单以显示给用户。我使用如下 LINQ 语句:

var newList = (from item in observable
select new { FirstInitial = item.Name[0] });

我知道这很初级,但足以证明问题。 (注意投影,这不是一个简单的过滤器或分组语句。)然后我通过数据绑定(bind)在我的 UI 中显示 newList。

问题是,当原始集合发生变化时,UI 不会。到目前为止,我应用的解决方案是将事件处理程序附加到原始集合的 CollectionChanged 事件,该事件重新评估查询并更新绑定(bind)属性。

虽然这很好用,但每次我遇到这种情况时都会重复很多代码。有没有办法让 LINQ 查询返回一个 ObservableCollection,当源 Observable 更改时“自动”更新?

换句话说,我想实现一些“固定”功能,以便在遇到这种情况时可以简单地重用它。

更新

感谢 Scroog1 帮助我看到我的原始帖子与 UI 的耦合度太高,无法满足我的真正要求。以下面的例子来更好地描述问题:
public class SomeClass
{
private ObservableCollection<Employee> _allEmployees;
private ObservableCollection<Employee> _currentEmployees;

public ObservableCollection<Employee> CurrentEmployees
{
get
{
if (_currentEmployees == null)
_currentEmployees = _allEmployees.Where(e => !e.IsTerminated);

return _currentEmployees;
}
}
}

public class SomeViewModel
{
private ICollectionView _view;

public ICollectionView CurrentView
{
if (_view == null)
{
var cvs = new CollectionViewSource()
{
Source = someClass.CurrentEmployees
}

cvs.Add(new SortDescription("Name", ListSortDirection.Ascending));

_view = cvs.View;
}

return _view;
}
}

如您所见,查询所在的代码并不是直接绑定(bind)到 UI 的。我使用这个例子来证明我是从更一般的用例而不是严格的 UI 数据绑定(bind)场景中询问的。

最佳答案

我会做这样的事情(假设一个名为 observable 的 ObservableCollection 和使用 RaisePropertyChanged 方法实现 INotifyPropertyChanged 的​​类):

public IEnumerable<string> NewList
{
return from item in observable
select item.Name;
}

observable.CollectionChanged += delegate { RaisePropertyChanged("NewList"); };

然后当 observable 改变时,UI 会被告知 NewList 已经改变并重新评估查询。

对于多个依赖项,您可以执行以下操作:
observable.CollectionChanged += delegate
{
RaisePropertyChanged("NewList",
"OtherProperty",
"YetAnotherProperty",
"Etc");
};

更新

上述内容通常适用于属性,因为您每次访问它时都会获得最新值,并且 INPC 可用于告诉事情以重新读取它。

对于稍微有趣的集合案例,我将实现一个自定义类,该类实现 INotifyCollectionChanged 和 IEnumerable 并包装 LINQ。例如。,
public class CustomObservableCollection<T> : INotifyCollectionChanged,
INotifyPropertyChanged,
IEnumerable<T>
{
private readonly IEnumerable<T> _collection;
public CustomObservableCollection(IEnumerable<T> collection)
{
_collection = collection;
}
public IEnumerator<T> GetEnumerator()
{
_collection.GetEnumerator();
}
public void RaiseCollectionChanged() { ... }
...
}

然后你可以这样做:
var newList = new CustomObservableCollection(from item in observable
select item.Name);
observable.CollectionChanged += delegate { newList.RaiseCollectionChanged(); };

更新 2

您甚至可以将依赖项传递给 CustomObservableCollection:
public class CustomObservableCollection<T> : INotifyCollectionChanged,
INotifyPropertyChanged,
IEnumerable<T>
{
private readonly IEnumerable<T> _collection;
public CustomObservableCollection(IEnumerable<T> collection,
params ObservableCollection[] dependencies)
{
_collection = collection;
foreach (var dep in dependencies)
dep.CollectionChanged += RaiseCollectionChanged();
}
public IEnumerator<T> GetEnumerator()
{
_collection.GetEnumerator();
}
public void RaiseCollectionChanged() { ... }
...
}

关于.net - ObservableCollection 更改时重新评估 LINQ 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10398014/

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