Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enabling LINQ for BindingListView<T>

Tags:

c#

linq

winforms

Andrew Davies created an excellent little class on sourceforge called BindingListView<T> which essentially allows you to bind a collection to a DataGridView while supporting sorting and filtering. Binding a DataGridView to a normal List<T> does not support sorting and filtering, as the proper interfaces are not implemented by List<T>.

The class works great and has solved my UI problems. However, it'd be awesome if I could iterate through the collection using LINQ, but I'm just not sure how to set it up to do so. Source code can be downloaded here. Can anyone help me out?

like image 400
Ken Avatar asked Jun 06 '11 18:06

Ken


2 Answers

Because the BindingListView<T> project uses .NET Framework v2.0 and predates LINQ, it doesn't expose an IEnumerable<T> for you to query on. Since it does implement non-generic IEnumerable and non-generic IList, you can use Enumerable.Cast<TResult> to convert the collection into a form suitable for use with LINQ. However, this approach isn't that helpful because the IEnumerable that AggregateBindingListView<T> returns is an internal data structure with type KeyValuePair<ListItemPair<T>, int>.

To upgrade this project for convenient use with LINQ, the simplest approach might be to implement IEnumerable<T> on AggregateBindingListView<T>. First add it to the declaration of the class:

public class AggregateBindingListView<T> : Component, IBindingListView, IList, IRaiseItemChangedEvents, ICancelAddNew, ITypedList, IEnumerable<T>

and then implement it at the end of the class definition:

#region IEnumerable<T> Members

IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
    for (int i = 0; i < _sourceIndices.Count; i++)
        yield return _sourceIndices[i].Key.Item.Object;

}

#endregion

and now you can use LINQ directly on a BindingListView<T> instance like this:

// Create a view of the items
itemsView = new BindingListView<Item>(feed.Items);
var descriptions = itemsView.Select(t => t.Description);

Remember to upgrade all the projects from .NET Framework v2.0 to .NET Framework 4 Client Profile and add using System.Linq; in order for this to work with your current project.

like image 107
Rick Sladkey Avatar answered Oct 14 '22 00:10

Rick Sladkey


Ok this is what I got: Here is my extension method :

public static class BindingViewListExtensions
{
  public static void Where<T>(this BindingListView<T> list, Func<T, bool> function)
  {
    // I am not sure I like this, but we know it is a List<T>
    var lists = list.DataSource as List<T>;

    foreach (var item in lists.Where<T>(function))
    {
        Console.WriteLine("I got item {0}", item);
    }
  }

}

And then I used it like :

    List<string> source = new List<string>() { "One", "Two", "Thre" };

    BindingListView<string> binding = new BindingListView<string>(source);

    binding.Where<string>(xx => xx == "One");

I guess where in the extension method could return the found item.

like image 33
MBen Avatar answered Oct 14 '22 01:10

MBen