最終編集/回答: DataGridView に組み込まれている並べ替えメカニズムを使用しながら、これを行う方法は考えられません。私があなたの立場なら、おそらく各列の SortMode を「Programmatic」に変更してから、「ColumnHeaderMouseClick」を自分で処理するでしょう。その時点で、変更された BindingList クラスでソート メソッドを呼び出す必要があります。このメソッドは、クリックされた列に従って必要に応じてソートを実行します。これにより、DGV の Sort メソッドの使用が回避され、基になるリストが直接並べ替えられます。
完全な談話はコメントセクションにあります。元の回答はすぐに続きます:
編集:問題に関する混乱とその後の議論のため、この回答のコメントに新しい提案があります。参照できるように、投稿した元の回答を残します。
私は最近これをしなければなりませんでした - そして私はそれが本当に苦痛だったと嘘をつきません. 私は解決策を思いつきました(ここSOの友人の助けを借りて)ので、ここに行きます。列と方向の両方を指定できる新しい IComparer ベースのインターフェイスを作成しました。これを行ったのは、ソート コードをできるだけ汎用にする必要があるためです。このようにソートする必要がある 2 つのグリッドがあり、2 倍のコードを維持したくありません。非常にシンプルなインターフェースは次のとおりです。
public interface IByColumnComparer : IComparer
{
string SortColumn { get; set; }
bool SortDescending { get; set; }
}
明らかに、一般的なものを維持することを心配していない場合 (おそらくそうするべきです)、これは厳密には必要ありません。次に、BindingList<> に基づく新しいクラスを作成しました。これにより、並べ替えコードをオーバーライドし、列ごとに独自の IByColumnComparer を提供できるようになりました。これにより、必要な柔軟性が得られました。これをチェックしてください:
public class SortableGenericCollection<T> : BindingList<T>
{
IByColumnComparer GenericComparer = null;
public SortableGenericCollection(IByColumnComparer SortingComparer)
{
GenericComparer = SortingComparer;
}
protected override bool SupportsSortingCore
{
get
{
return true;
}
}
protected override bool IsSortedCore
{
get
{
for (int i = 0; i < Items.Count - 1; ++i)
{
T lhs = Items[i];
T rhs = Items[i + 1];
PropertyDescriptor property = SortPropertyCore;
if (property != null)
{
object lhsValue = lhs == null ? null :
property.GetValue(lhs);
object rhsValue = rhs == null ? null :
property.GetValue(rhs);
int result;
if (lhsValue == null)
{
result = -1;
}
else if (rhsValue == null)
{
result = 1;
}
else
{
result = GenericComparer.Compare(lhs, rhs);
}
if (result >= 0)
{
return false;
}
}
}
return true;
}
}
private ListSortDirection sortDirection;
protected override ListSortDirection SortDirectionCore
{
get
{
return sortDirection;
}
}
private PropertyDescriptor sortProperty;
protected override PropertyDescriptor SortPropertyCore
{
get
{
return sortProperty;
}
}
protected override void ApplySortCore(PropertyDescriptor prop,
ListSortDirection direction)
{
sortProperty = prop;
sortDirection = direction;
GenericComparer.SortColumn = prop.Name;
GenericComparer.SortDescending = direction == ListSortDirection.Descending ? true : false;
List<T> list = (List<T>)Items;
list.Sort(delegate(T lhs, T rhs)
{
if (sortProperty != null)
{
object lhsValue = lhs == null ? null :
sortProperty.GetValue(lhs);
object rhsValue = rhs == null ? null :
sortProperty.GetValue(rhs);
int result;
if (lhsValue == null)
{
result = -1;
}
else if (rhsValue == null)
{
result = 1;
}
else
{
result = GenericComparer.Compare(lhs, rhs);
}
return result;
}
else
{
return 0;
}
});
}
protected override void RemoveSortCore()
{
sortDirection = ListSortDirection.Ascending;
sortProperty = null;
}
}
今、ApplySortCore メソッドでわかるように、列と方向を DataGridView から直接受け取っています。つまり、これをプログラムで呼び出していないということです。これはやりたいことのようには思えませんが、プログラムで呼び出して適切な IByColumnComparer を渡す必要がある場合は、このコードを簡単に変更できます。このすべてをお見せする私のポイントは、ソート アルゴリズムを変更する方法を理解できるようにすることです。これは非常に便利です。
このクラスをより一般的にすることに関する提案について、@MartinhoFernandes に感謝します。