Pau*_*ett 21 .net c# sorting bindinglist winforms
我正在尝试编写一个可用于我的应用程序的SortableBindingList.我发现了很多关于如何实现基本排序支持的讨论,以便BindingList在DataGridView或其他绑定控件的上下文中使用时进行排序,包括来自StackOverflow的这篇文章:
DataGridView排序和例如.NET中的BindingList <T>
这一切都非常有用,我已经实现了代码,经过测试等等,并且一切正常,但在我的特殊情况下,我需要能够支持对Sort()的简单调用,并让该调用使用默认的IComparable. CompareTo()进行排序,而不是调用ApplySortCore(PropertyDescriptor,ListSortDirection).
原因是因为我有很多代码依赖于Sort()调用,因为这个特定的类最初是从List继承的,最近被改为BindingList.
具体来说,我有一个名为VariableCode的类和一个名为VariableCodeList的集合类.VariableCode实现IComparable,其中的逻辑基于几个属性等适度复杂...
public class VariableCode : ... IComparable ...
{
public int CompareTo(object p_Target)
{
int output = 0;
//some interesting stuff here
return output;
}
}
public class VariableCodeList : SortableBindingList<VariableCode>
{
public void Sort()
{
//This is where I need help
// How do I sort this list using the IComparable
// logic from the class above?
}
}
Run Code Online (Sandbox Code Playgroud)
我在Sort()中重新调整了ApplySortCore方法的尝试失败了,但是阻止我的是,ApplySortCore期望PropertyDescriptor进行排序,我无法弄清楚如何使用IComparable .CompareTo()逻辑.
有人能指出我正确的方向吗?
非常感谢.
编辑:这是基于Marc的回复的最终代码,供将来参考.
/// <summary>
/// Sorts using the default IComparer of T
/// </summary>
public void Sort()
{
sort(null, null);
}
public void Sort(IComparer<T> p_Comparer)
{
sort(p_Comparer, null);
}
public void Sort(Comparison<T> p_Comparison)
{
sort(null, p_Comparison);
}
private void sort(IComparer<T> p_Comparer, Comparison<T> p_Comparison)
{
m_SortProperty = null;
m_SortDirection = ListSortDirection.Ascending;
//Extract items and sort separately
List<T> sortList = new List<T>();
this.ForEach(item => sortList.Add(item));//Extension method for this call
if (p_Comparison == null)
{
sortList.Sort(p_Comparer);
}//if
else
{
sortList.Sort(p_Comparison);
}//else
//Disable notifications, rebuild, and re-enable notifications
bool oldRaise = RaiseListChangedEvents;
RaiseListChangedEvents = false;
try
{
ClearItems();
sortList.ForEach(item => this.Add(item));
}
finally
{
RaiseListChangedEvents = oldRaise;
ResetBindings();
}
}
Run Code Online (Sandbox Code Playgroud)
Mar*_*ell 16
模拟一个属性只是为了进行排序可能有点过头了.首先要看的是Comparer<T>.Default.然而,可能最简单的事情是:
List<T>或类似顺便说一句,您应该在现有排序期间禁用通知.
public void Sort() {
// TODO: clear your "sort" variables (prop/order)
T[] arr = new T[Count];
CopyTo(arr, 0);
Array.Sort(arr);
bool oldRaise = RaiseListChangedEvents;
RaiseListChangedEvents = false; // <=== oops, added!
try {
ClearItems();
foreach (T item in arr) {
Add(item);
}
} finally {
RaiseListChangedEvents = oldRaise;
ResetBindings();
}
}
Run Code Online (Sandbox Code Playgroud)
Sol*_*arX 10
我有同样的问题,这篇文章帮我解决了!
当我实现这个解决方案(基于Marc和Paul的代码)作为扩展并添加了两个简单的排序方法时,我想与您分享:
public static void SortAscending<T, P>(this BindingList<T> bindingList, Func<T, P> sortProperty)
{
bindingList.Sort(null, (a, b) => ((IComparable<P>)sortProperty(a)).CompareTo(sortProperty(b)));
}
public static void SortDescending<T, P>(this BindingList<T> bindingList, Func<T, P> sortProperty)
{
bindingList.Sort(null, (a, b) => ((IComparable<P>)sortProperty(b)).CompareTo(sortProperty(a)));
}
public static void Sort<T>(this BindingList<T> bindingList)
{
bindingList.Sort(null, null);
}
public static void Sort<T>(this BindingList<T> bindingList, IComparer<T> comparer)
{
bindingList.Sort(comparer, null);
}
public static void Sort<T>(this BindingList<T> bindingList, Comparison<T> comparison)
{
bindingList.Sort(null, comparison);
}
private static void Sort<T>(this BindingList<T> bindingList, IComparer<T> p_Comparer, Comparison<T> p_Comparison)
{
//Extract items and sort separately
List<T> sortList = new List<T>();
bindingList.ForEach(item => sortList.Add(item));//Extension method for this call
if (p_Comparison == null)
{
sortList.Sort(p_Comparer);
}//if
else
{
sortList.Sort(p_Comparison);
}//else
//Disable notifications, rebuild, and re-enable notifications
bool oldRaise = bindingList.RaiseListChangedEvents;
bindingList.RaiseListChangedEvents = false;
try
{
bindingList.Clear();
sortList.ForEach(item => bindingList.Add(item));
}
finally
{
bindingList.RaiseListChangedEvents = oldRaise;
bindingList.ResetBindings();
}
}
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{
if (source == null) throw new ArgumentNullException("source");
if (action == null) throw new ArgumentNullException("action");
foreach (T item in source)
{
action(item);
}
}
Run Code Online (Sandbox Code Playgroud)
希望这是有帮助的.