Могу ли я привести результат запроса LINQ к BindingList <T>? - PullRequest
1 голос
/ 06 февраля 2010

Из того, что я узнал, вы не можете привести к BindingList, но вы можете обернуть свой результат из запроса Linq с помощью NEW BindingList. Однако, это не работает для меня, потому что к моему списку оригинальных привязок прикреплены некоторые события, и я хотел бы сохранить те же события в моем наборе результатов LINQ.

Например:

У меня есть моя основная коллекция 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?

Спасибо за помощь

Ответы [ 2 ]

3 голосов
/ 06 февраля 2010

Я не думаю, что есть простой способ сделать это. Я бы сделал производную 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;
0 голосов
/ 06 февраля 2010

Я думаю, что один из самых простых способов добиться этого - что-то вроде этого:

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));
        }
    }
}
...