过滤通用列表的最简单方法

我有以下类在我的表中定义一个条目(我删除了brewity的构造函数,它简单地设置了该数据):

class FilterResult { public bool Checked { get; set; } public string Url { get; private set;} public string Description { get; private set; } public int ItemID { get; private set; } } 

我使用它作为WinForms应用程序中的DataGridView的简单源,使用GUI中的“选择数据源”创建,这导致自动创建的类名为filterResultBindingSource

现在,这种方法不支持DataGridView.Filter属性,我需要能够对结果进行简单的过滤。

我怎样才能以最快/最简单的方式创建自定义列表,绑定源或第三个以支持过滤? 从我所看到的,实现IBindingListView或新的BindingSource有很多工作,但如果我错了,请纠正我。

它不一定要使用Filter属性,事实上如果我可以实现一个自定义方法可能会更容易,我可以使用列表中的Where -method进行过滤。

在sourceforge.net上查看BindingListView项目 。 该项目相当容易使用,下载包含有用的示例。

但是,对于快速且易于实现的解决方案,请查看此处提供的BindListView类(与sourceforge项目无关)(具体列出9.7)。 这是一个generics类,您可以将其设置为BindingSource的DataSource,并通过BindingSource的Filter属性进行过滤。 在我链接的文章中讨论了如何使用它的一些限制,但对我而言,它对于您正在寻找的快速解决方案来说是完美的。

我将补充说,您可以使用这两种解决方案来允许在DGV中进行排序。

编辑:几年前我用来获取BindingListView类的链接已经死了所以我发现它在其他地方。 我决定继续发布以下代码以供将来参考,以防此链接也消失。

 public class BindingListView : BindingList, IBindingListView, IRaiseItemChangedEvents { private bool m_Sorted = false; private bool m_Filtered = false; private string m_FilterString = null; private ListSortDirection m_SortDirection = ListSortDirection.Ascending; private PropertyDescriptor m_SortProperty = null; private ListSortDescriptionCollection m_SortDescriptions = new ListSortDescriptionCollection(); private List m_OriginalCollection = new List(); public BindingListView() : base() { } public BindingListView(List list) : base(list) { } protected override bool SupportsSearchingCore { get { return true; } } protected override int FindCore(PropertyDescriptor property, object key) { // Simple iteration: for (int i = 0; i < Count; i++) { T item = this[i]; if (property.GetValue(item).Equals(key)) { return i; } } return -1; // Not found // Alternative search implementation // using List.FindIndex: //Predicate pred = delegate(T item) //{ // if (property.GetValue(item).Equals(key)) // return true; // else // return false; //}; //List list = Items as List; //if (list == null) // return -1; //return list.FindIndex(pred); } protected override bool SupportsSortingCore { get { return true; } } protected override bool IsSortedCore { get { return m_Sorted; } } protected override ListSortDirection SortDirectionCore { get { return m_SortDirection; } } protected override PropertyDescriptor SortPropertyCore { get { return m_SortProperty; } } protected override void ApplySortCore(PropertyDescriptor property, ListSortDirection direction) { m_SortDirection = direction; m_SortProperty = property; SortComparer comparer = new SortComparer(property, direction); ApplySortInternal(comparer); } private void ApplySortInternal(SortComparer comparer) { if (m_OriginalCollection.Count == 0) { m_OriginalCollection.AddRange(this); } List listRef = this.Items as List; if (listRef == null) return; listRef.Sort(comparer); m_Sorted = true; OnListChanged(new ListChangedEventArgs( ListChangedType.Reset, -1)); } protected override void RemoveSortCore() { if (!m_Sorted) return; Clear(); foreach (T item in m_OriginalCollection) { Add(item); } m_OriginalCollection.Clear(); m_SortProperty = null; m_SortDescriptions = null; m_Sorted = false; } void IBindingListView.ApplySort(ListSortDescriptionCollection sorts) { m_SortProperty = null; m_SortDescriptions = sorts; SortComparer comparer = new SortComparer(sorts); ApplySortInternal(comparer); } string IBindingListView.Filter { get { return m_FilterString; } set { m_FilterString = value; m_Filtered = true; UpdateFilter(); } } void IBindingListView.RemoveFilter() { if (!m_Filtered) return; m_FilterString = null; m_Filtered = false; m_Sorted = false; m_SortDescriptions = null; m_SortProperty = null; Clear(); foreach (T item in m_OriginalCollection) { Add(item); } m_OriginalCollection.Clear(); } ListSortDescriptionCollection IBindingListView.SortDescriptions { get { return m_SortDescriptions; } } bool IBindingListView.SupportsAdvancedSorting { get { return true; } } bool IBindingListView.SupportsFiltering { get { return true; } } protected virtual void UpdateFilter() { int equalsPos = m_FilterString.IndexOf('='); // Get property name string propName = m_FilterString.Substring(0, equalsPos).Trim(); // Get filter criteria string criteria = m_FilterString.Substring(equalsPos + 1, m_FilterString.Length - equalsPos - 1).Trim(); // Strip leading and trailing quotes criteria = criteria.Substring(1, criteria.Length - 2); // Get a property descriptor for the filter property PropertyDescriptor propDesc = TypeDescriptor.GetProperties(typeof(T))[propName]; if (m_OriginalCollection.Count == 0) { m_OriginalCollection.AddRange(this); } List currentCollection = new List(this); Clear(); foreach (T item in currentCollection) { object value = propDesc.GetValue(item); if (value.ToString() == criteria) { Add(item); } } } bool IBindingList.AllowNew { get { return CheckReadOnly(); } } bool IBindingList.AllowRemove { get { return CheckReadOnly(); } } private bool CheckReadOnly() { if (m_Sorted || m_Filtered) { return false; } else { return true; } } protected override void InsertItem(int index, T item) { foreach (PropertyDescriptor propDesc in TypeDescriptor.GetProperties(item)) { if (propDesc.SupportsChangeEvents) { propDesc.AddValueChanged(item, OnItemChanged); } } base.InsertItem(index, item); } protected override void RemoveItem(int index) { T item = Items[index]; PropertyDescriptorCollection propDescs = TypeDescriptor.GetProperties(item); foreach (PropertyDescriptor propDesc in propDescs) { if (propDesc.SupportsChangeEvents) { propDesc.RemoveValueChanged(item, OnItemChanged); } } base.RemoveItem(index); } void OnItemChanged(object sender, EventArgs args) { int index = Items.IndexOf((T)sender); OnListChanged(new ListChangedEventArgs( ListChangedType.ItemChanged, index)); } bool IRaiseItemChangedEvents.RaisesItemChangedEvents { get { return true; } } } class SortComparer : IComparer { private ListSortDescriptionCollection m_SortCollection = null; private PropertyDescriptor m_PropDesc = null; private ListSortDirection m_Direction = ListSortDirection.Ascending; public SortComparer(PropertyDescriptor propDesc, ListSortDirection direction) { m_PropDesc = propDesc; m_Direction = direction; } public SortComparer(ListSortDescriptionCollection sortCollection) { m_SortCollection = sortCollection; } int IComparer.Compare(T x, T y) { if (m_PropDesc != null) // Simple sort { object xValue = m_PropDesc.GetValue(x); object yValue = m_PropDesc.GetValue(y); return CompareValues(xValue, yValue, m_Direction); } else if (m_SortCollection != null && m_SortCollection.Count > 0) { return RecursiveCompareInternal(x, y, 0); } else return 0; } private int CompareValues(object xValue, object yValue, ListSortDirection direction) { int retValue = 0; if (xValue is IComparable) { retValue = ((IComparable)xValue).CompareTo(yValue); } else if (yValue is IComparable) { retValue = ((IComparable)yValue).CompareTo(xValue); } // not comparable, compare String representations else if (!xValue.Equals(yValue)) { retValue = xValue.ToString().CompareTo(yValue.ToString()); } if (direction == ListSortDirection.Ascending) { return retValue; } else { return retValue * -1; } } private int RecursiveCompareInternal(T x, T y, int index) { if (index >= m_SortCollection.Count) return 0; // termination condition ListSortDescription listSortDesc = m_SortCollection[index]; object xValue = listSortDesc.PropertyDescriptor.GetValue(x); object yValue = listSortDesc.PropertyDescriptor.GetValue(y); int retValue = CompareValues(xValue, yValue, listSortDesc.SortDirection); if (retValue == 0) { return RecursiveCompareInternal(x, y, ++index); } else { return retValue; } } } 

我认为使用通用List对象最简单的方法是将其转换为DataTable。

  public Form1( ) { InitializeComponent( ); List list = new List( ); list.Add( new Item( 1, "ITEM 001" ) ); list.Add( new Item( 2, "ITEM 002" ) ); list.Add( new Item( 3, "ITEM 003" ) ); list.Add( new Item( 4, "ITEM 004" ) ); list.Add( new Item( 5, "ITEM 005" ) ); list.Add( new Item( 6, "ITEM 006" ) ); list.Add( new Item( 7, "ITEM 007" ) ); list.Add( new Item( 100, "SW-RED" ) ); list.Add( new Item( 101, "SW-BLUE" ) ); list.Add( new Item( 102, "SW-GREEN" ) ); list.Add( new Item( 103, "SW-BLACK" ) ); list.Add( new Item( 104, "SW-WHITE" ) ); // convert list to table DataTable dt = new DataTable( ); dt = Convert.ToDataTable( list ); DataView view = dt.AsDataView( ); view.RowFilter = "ItemID < 100"; comboBox1.DataSource = view; comboBox1.ValueMember = "ItemID"; comboBox1.DisplayMember = "Description"; }