根据我所学到的,你不能转换为BindingList,而是可以使用NEW BindingList包装Linq查询的结果。但是,这对我不起作用,因为我的原始绑定列表附加了一些事件,我想在我的LINQ结果集中保持相同的事件。
例如:
我有一个名为“Reports”的主要BindingList集合(类型为IReport)。此集合正在注册到以下事件: Reports.AddingNew + = OnAddNewXReport;
现在,当我想过滤这个大集合并只提取几个匹配的项目时,我正在使用Linq获取此匹配列表。为了使这个列表成为一个BindingList,我新增了以下内容:
var rs = Reports.Where(r => r.ReportType == ReportType.MyType).Select(o => (MyType) o);
return new BindingList<MyType>(rs.ToList());
如您所见,这个新创建的集合在添加新项目时不会触发。
有谁知道如何解决这个问题?无论如何关闭事件订阅从原始BindingList到“过滤”BindingList?
感谢您的帮助
答案 0 :(得分:3)
我认为有一种简单的方法可以做到这一点。我会创建一个派生的BindingList<T>
链接并公开你感兴趣的事件。
sealed class MyBindingList<T> : BindingList<T>
{
public event EventHandler MyAddingNew;
public MyBindingList(IList<T> collection)
: base(collection)
{
//hook so that when BindingList.AddingNew is fired
//it is chained to our new event
base.AddingNew += MyBindingList_AddingNew;
}
public void MyBindingList_AddingNew(object sender, AddingNewEventArgs e)
{
if (MyAddingNew != null)
MyAddingNew(sender, e);
}
public void RegisterEvents(MyBindingList<T> src)
{
//this is where you assign src events to your new list
this.MyAddingNew = src.MyAddingNew;
}
}
您需要派生类型的原因是您不能仅使用EventHandlers
(=
)分配this.AddingNew = src.AddingNew
,除非您在定义它的范围内。当翻译成您的代码时,您将拥有:
MyBindingList<MyType> Reports;
Reports.MyAddingNew += OnAddNewXReport;
var rs = Reports.Where(r => r.ReportType == ReportType.MyType)
.Select(o => (MyType) o);
MyBindingList<MyType> FilteredReports = new MyBindingList<MyType>(rs.ToList());
FilteredReports.RegisterEvents(Reports);
return FilteredReports;
答案 1 :(得分:0)
我认为实现这一目标的最简单方法之一就是:
var rs = Reports.Where(r => r.ReportType == ReportType.MyType).Select(o => (MyType) o);
var bs = new BindingList<MyType>();
foreach(var r in rs)
bs.Add(r);
另一种方法是为BindingList创建后代,并在构造函数中为新列表中的每个项触发OnListChanged:
sealed class MyBindingList<T> : BindingList<T>
{
public MyBindingList(IList<T> collection)
: base(collection)
{
for(int i = 0; i < collection.Count; ++i)
{
OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded, idx));
}
}
}