使用 SortableBindingList<T> - DataGridView 不会自动对更改进行排序
Using SortableBindingList<T> - DataGridView doesn't automatically sort on changes
我正在构建一个显示自定义 class Record
objects 的 Windows 表单应用程序,并根据它们在我的 SortableBindingList<Record>
record_list
。当我启动我的程序时,为了测试,我已经将一些 "dummy" 记录加载到此列表中。
SortableBindingList<T>
取自 here。
public partial class Form1 : Form
{
public SortableBindingList<Record> record_list = new SortableBindingList<Record> { };
public static DataGridViewCellStyle style = new DataGridViewCellStyle();
public Form1()
{
InitializeComponent();
dataGridView.DataSource = record_list;
FillData(); //Temporary function to insert dummy data for demo.
dataGridView.CellFormatting += new System.Windows.Forms.DataGridViewCellFormattingEventHandler(this.cell_formatting);
this.Controls.Add(dataGridView);
this.dataGridView.RowHeadersVisible = false;
this.dataGridView.Sort(this.dataGridView.Columns["UserName"], ListSortDirection.Ascending);
start_timer();
}
添加 "new" 数据之前的结果(注意:这是自动按字母顺序排列的,特别是不按字母顺序输入列表):
添加数据后的结果:
最后,点击 "UserName" header 后的结果:
那么,每次我的数据源更新时我都必须强制排序吗?如果是这样,我如何以这种方式调用排序?
提前感谢您的协助!
您需要在列表更改时应用排序。
SortableBindingList<T>
需要进行一些更改以在列表中进行某些更改时保持列表排序。这是我所做更改的完整代码。
注意BindingList
的OnListChanged
方法会在添加和删除项目后自动调用。但是,如果您需要 OnListChanged
在更改项目属性后也运行,您应该为您的模型 class.
实施 INotifyPropertyChanged
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
public class SortableBindingList<T> : BindingList<T>
{
private bool isSortedValue;
ListSortDirection sortDirectionValue;
PropertyDescriptor sortPropertyValue;
public SortableBindingList() : base() { }
public SortableBindingList(IList<T> list) : base(list) { }
protected override void ApplySortCore(PropertyDescriptor prop,
ListSortDirection direction)
{
Type interfaceType = prop.PropertyType.GetInterface("IComparable");
if (interfaceType == null && prop.PropertyType.IsValueType)
{
Type underlyingType = Nullable.GetUnderlyingType(prop.PropertyType);
if (underlyingType != null)
{
interfaceType = underlyingType.GetInterface("IComparable");
}
}
if (interfaceType != null)
{
sortPropertyValue = prop;
sortDirectionValue = direction;
IEnumerable<T> query = base.Items;
if (direction == ListSortDirection.Ascending)
query = query.OrderBy(i => prop.GetValue(i));
else
query = query.OrderByDescending(i => prop.GetValue(i));
int newIndex = 0;
foreach (object item in query)
{
this.Items[newIndex] = (T)item;
newIndex++;
}
isSortedValue = true;
sorting = true;
this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
sorting = false;
}
else
{
throw new NotSupportedException("Cannot sort by " + prop.Name +
". This" + prop.PropertyType.ToString() +
" does not implement IComparable");
}
}
bool sorting = false;
protected override PropertyDescriptor SortPropertyCore
{
get { return sortPropertyValue; }
}
protected override ListSortDirection SortDirectionCore
{
get { return sortDirectionValue; }
}
protected override bool SupportsSortingCore
{
get { return true; }
}
protected override bool IsSortedCore
{
get { return isSortedValue; }
}
protected override void RemoveSortCore()
{
isSortedValue = false;
sortPropertyValue = null;
}
protected override void OnListChanged(ListChangedEventArgs e)
{
if (!sorting && sortPropertyValue != null)
ApplySortCore(sortPropertyValue, sortDirectionValue);
else
base.OnListChanged(e);
}
}
我正在构建一个显示自定义 class Record
objects 的 Windows 表单应用程序,并根据它们在我的 SortableBindingList<Record>
record_list
。当我启动我的程序时,为了测试,我已经将一些 "dummy" 记录加载到此列表中。
SortableBindingList<T>
取自 here。
public partial class Form1 : Form
{
public SortableBindingList<Record> record_list = new SortableBindingList<Record> { };
public static DataGridViewCellStyle style = new DataGridViewCellStyle();
public Form1()
{
InitializeComponent();
dataGridView.DataSource = record_list;
FillData(); //Temporary function to insert dummy data for demo.
dataGridView.CellFormatting += new System.Windows.Forms.DataGridViewCellFormattingEventHandler(this.cell_formatting);
this.Controls.Add(dataGridView);
this.dataGridView.RowHeadersVisible = false;
this.dataGridView.Sort(this.dataGridView.Columns["UserName"], ListSortDirection.Ascending);
start_timer();
}
添加 "new" 数据之前的结果(注意:这是自动按字母顺序排列的,特别是不按字母顺序输入列表):
添加数据后的结果:
最后,点击 "UserName" header 后的结果:
那么,每次我的数据源更新时我都必须强制排序吗?如果是这样,我如何以这种方式调用排序?
提前感谢您的协助!
您需要在列表更改时应用排序。
SortableBindingList<T>
需要进行一些更改以在列表中进行某些更改时保持列表排序。这是我所做更改的完整代码。
注意BindingList
的OnListChanged
方法会在添加和删除项目后自动调用。但是,如果您需要 OnListChanged
在更改项目属性后也运行,您应该为您的模型 class.
INotifyPropertyChanged
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
public class SortableBindingList<T> : BindingList<T>
{
private bool isSortedValue;
ListSortDirection sortDirectionValue;
PropertyDescriptor sortPropertyValue;
public SortableBindingList() : base() { }
public SortableBindingList(IList<T> list) : base(list) { }
protected override void ApplySortCore(PropertyDescriptor prop,
ListSortDirection direction)
{
Type interfaceType = prop.PropertyType.GetInterface("IComparable");
if (interfaceType == null && prop.PropertyType.IsValueType)
{
Type underlyingType = Nullable.GetUnderlyingType(prop.PropertyType);
if (underlyingType != null)
{
interfaceType = underlyingType.GetInterface("IComparable");
}
}
if (interfaceType != null)
{
sortPropertyValue = prop;
sortDirectionValue = direction;
IEnumerable<T> query = base.Items;
if (direction == ListSortDirection.Ascending)
query = query.OrderBy(i => prop.GetValue(i));
else
query = query.OrderByDescending(i => prop.GetValue(i));
int newIndex = 0;
foreach (object item in query)
{
this.Items[newIndex] = (T)item;
newIndex++;
}
isSortedValue = true;
sorting = true;
this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
sorting = false;
}
else
{
throw new NotSupportedException("Cannot sort by " + prop.Name +
". This" + prop.PropertyType.ToString() +
" does not implement IComparable");
}
}
bool sorting = false;
protected override PropertyDescriptor SortPropertyCore
{
get { return sortPropertyValue; }
}
protected override ListSortDirection SortDirectionCore
{
get { return sortDirectionValue; }
}
protected override bool SupportsSortingCore
{
get { return true; }
}
protected override bool IsSortedCore
{
get { return isSortedValue; }
}
protected override void RemoveSortCore()
{
isSortedValue = false;
sortPropertyValue = null;
}
protected override void OnListChanged(ListChangedEventArgs e)
{
if (!sorting && sortPropertyValue != null)
ApplySortCore(sortPropertyValue, sortDirectionValue);
else
base.OnListChanged(e);
}
}