我有以下类在我的表中定义一个条目(我删除了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
方法进行过滤。
答案 0 :(得分:8)
在sourceforge.net上查看BindingListView project。这个项目相当容易使用,下载包含有用的样本。
但是,对于快速且易于实现的解决方案,请查看呈现here的BindListView类(与sourceforge项目无关)(具体列出9.7)。这是一个泛型类,您可以将其设置为BindingSource的DataSource,并通过BindingSource的Filter属性进行过滤。在我链接的文章中讨论了如何使用它的一些限制,但对我而言,这对于您正在寻找的快速解决方案来说是完美的。
我将补充说,您可以使用这两种解决方案来允许在您的DGV中进行排序。
修改强> 几年前我用来获取BindingListView类的链接已经死了,所以我发现它在其他地方。我决定继续发布以下代码以供将来参考,以防此链接也消失。
public class BindingListView<T> : BindingList<T>, 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<T> m_OriginalCollection = new List<T>();
public BindingListView()
: base() {
}
public BindingListView(List<T> 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<T> pred = delegate(T item)
//{
// if (property.GetValue(item).Equals(key))
// return true;
// else
// return false;
//};
//List<T> list = Items as List<T>;
//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<T> comparer = new SortComparer<T>(property, direction);
ApplySortInternal(comparer);
}
private void ApplySortInternal(SortComparer<T> comparer) {
if (m_OriginalCollection.Count == 0) {
m_OriginalCollection.AddRange(this);
}
List<T> listRef = this.Items as List<T>;
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<T> comparer = new SortComparer<T>(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<T> currentCollection = new List<T>(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<T> : IComparer<T>
{
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<T>.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;
}
}
}
答案 1 :(得分:5)
我认为使用通用List对象最简单的方法是将其转换为DataTable。
public Form1( )
{
InitializeComponent( );
List<Item> list = new List<Item>( );
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<Item>( list );
DataView view = dt.AsDataView( );
view.RowFilter = "ItemID < 100";
comboBox1.DataSource = view;
comboBox1.ValueMember = "ItemID";
comboBox1.DisplayMember = "Description";
}