I have a very simple database for which I use linq for sql. I have a datagridview to show the contents of a table. I want the user to be able to filter the rows that appear in the datagridview, if possible, without making another query to the database (I really have few resources, so the solution should be as fast as possible).
I was thinking about using the Filter property of the BindingSource class, so I created it, set the DataSource property to express linq to sql. When the user added a filter, I set the Filter property. After half an hour, I found out that BindingSource does not support filtering. Damn, great; but then what? After spending another half hour using Google and using almost nothing, I cheated to use System.Collections.Generic.List to store strings, because I can filter it out. Everything was fine, but I also needed to keep the original list (in case the user deletes the filter), and I also need to support several filters.
So, I had two lists: one with all the lines that resulted in the request, and one with the lines that matched the filter conditions. I have not tested it with a few filters.
It worked, although it was not a very good solution (at least I did not find it attractive), but that was all I had. I cheated to write a wrapper class because I might need to reuse this solution anytime later. I was thinking of creating a FilteredList class (after I did some search queries with Google and did not find any existing implementations) based on the following theory:
- I save a list with all the rows in a table,
- I store filters (which are predictive expressions) in a BindingList (so that I can find out if the list has changed and filter the lines)
- , , ,
- (_NeedsRefiltering), , ,
- IList, DataSource DataGridView.
FilteredList:
public class FilteredList<T> : IList<T>
{
private bool _NeedsReFiltering = false;
private BindingList<Predicate<T>> _Filters;
public BindingList<Predicate<T>> Filters
{
get
{
if (this._Filters == null)
{
this._Filters = new BindingList<Predicate<T>>();
this._Filters.RaiseListChangedEvents = true;
this._Filters.ListChanged += delegate(object sender, ListChangedEventArgs e)
{
this._NeedsReFiltering = true;
};
}
return this._Filters;
}
set
{
this._Filters = value;
this._NeedsReFiltering = true;
}
}
private List<T> _Source;
public List<T> Source
{
get
{
return this._Source;
}
set
{
this._Source = value;
this._NeedsReFiltering = true;
}
}
private List<T> __FilteredSource = new List<T>();
private List<T> _FilteredSource
{
get
{
if (this._NeedsReFiltering)
{
this._NeedsReFiltering = false;
this.Refilter();
}
return this.__FilteredSource;
}
set
{
this.__FilteredSource = value;
}
}
public List<T> FilteredSource
{
get
{
return this._FilteredSource;
}
}
public FilteredList()
{
this._Source = new List<T>();
}
public FilteredList(int capacity)
{
this._Source = new List<T>(capacity);
}
public FilteredList(IEnumerable<T> source)
{
this._Source = new List<T>(source);
this._NeedsReFiltering = true;
}
public void Refilter()
{
this.__FilteredSource = this._Source;
if (this._Filters == null)
{
return;
}
foreach (var filter in this._Filters)
{
this.__FilteredSource.RemoveAll(item => !filter(item));
}
}
public int IndexOf(T item)
{
return this._FilteredSource.IndexOf(item);
}
public void Insert(int index, T item)
{
this._FilteredSource.Insert(index, item);
this._Source.Add(item);
}
public void RemoveAt(int index)
{
this._Source.Remove(this.__FilteredSource[index]);
this._NeedsReFiltering = true;
}
public T this[int index]
{
get
{
return this._FilteredSource[index];
}
set
{
this._Source[this._Source.FindIndex(item => item.Equals(this._FilteredSource[index]))] = value;
this._NeedsReFiltering = true;
}
}
public void Add(T item)
{
this._Source.Add(item);
this._NeedsReFiltering = true;
}
public void Clear()
{
this._Source.Clear();
this._FilteredSource.Clear();
this._NeedsReFiltering = false;
}
public bool Contains(T item)
{
return this._FilteredSource.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
this._FilteredSource.CopyTo(array, arrayIndex);
}
public int Count
{
get { return this._FilteredSource.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
public bool Remove(T item)
{
var r = this._Source.Remove(item);
this._FilteredSource.Remove(item);
return r;
}
public IEnumerator<T> GetEnumerator()
{
return this._FilteredSource.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this._FilteredSource.GetEnumerator();
}
}
- ( ), , . , , , DataGridView, , DataSource: , ( datagridview, - , , ). , . _FilteredSource , - , : System.IndexOutOfRangeException: 180 .
:
alt text http://shadow.crysis.hu/dgv_error.png
, , . DataGridView Invalidate, Update Refresh - .
...
- , DataGridView, linq to sql?
- FilteredList DataGridView?
- ?
( ) ()!
, , , System.Collections.IList . , DataSource DataGridView, , ( - , ) Invalidate(), Refresh() Update() ), IndexOutOfRangeException, DataError-s.
, ? , linq to sql datagridview (, )...