2010-02-05 16 views
1

D'après ce que j'ai appris, vous ne pouvez pas convertir en BindingList, mais vous pouvez envelopper votre résultat de la requête Linq avec une NOUVELLE BindingList. Cependant, cela ne fonctionne pas pour moi, parce que ma liste de liaison d'origine a des événements qui s'y rattachent et je voudrais maintenir les mêmes événements dans mon ensemble de résultats LINQ.Puis-je transmettre un résultat de requête LINQ à BindingList <T>?

Par exemple:

J'ai ma principale collection de BindingList appelé "Rapports" (de type IReport). Cette collection est enregistrée dans un événement comme suit: Reports.AddingNew + = OnAddNewXReport;

maintenant, quand je voudrais filtrer cette grande collection et extraire seulement quelques éléments assortis, j'utilise Linq pour obtenir cette liste correspondante. Pour cette liste un BindingList, i nouveau pour effectuer les opérations suivantes:

var rs = Reports.Where(r => r.ReportType == ReportType.MyType).Select(o => (MyType) o); 

return new BindingList<MyType>(rs.ToList()); 

Comme vous pouvez le voir, cette collection nouvellement créée, ne se déclenche pas lorsque nouvel élément est ajouté.

Est-ce que quelqu'un a une idée de la façon de résoudre ce problème? existe-t-il de toute façon pour fermer l'abonnement à l'événement de BindingList d'origine à BindingList "filtré"?

Merci pour l'aide

+0

peut vous pouvez ou pouvez vous ne pouvez pas? ;-) –

Répondre

3

Je ne pense pas qu'il y ait un moyen facile de le faire. Je fais un BindingList<T> dérivés que les chaînes et expose les événements qui vous intéressent.

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

Raison pour laquelle vous auriez besoin d'un type dérivé est que vous ne pouvez pas affecter EventHandlers en utilisant seulement = (this.AddingNew = src.AddingNew) à moins que vous êtes la portée qui le définit. Lorsque traduit dans votre code que vous auriez:

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

Je pense que l'un des plus simple moyen d'y parvenir est quelque chose comme ceci:

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

Une autre façon est de créer un descendant pour BindingList et dans les feux de constructeur OnListChanged pour chaque article dans la nouvelle liste:

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)); 
     } 
    } 
} 
+2

Je ne pense pas qu'il voulait des façons de créer un nouveau 'BindingList 'à partir de ses éléments (vu comme il le fait déjà avec' new BindingList (rs.ToList()); ') mais plutôt un moyen que les événements qui sont enregistrés sur 'Reports' sont transférés vers le nouveau' BindingList' –

+1

Dans mon cas, le résultat serait le même, mais GUI contiendrait toutes les nouvelles valeurs. Ou je ne comprends pas ce que signifie "transféré"? –