I took your question as a small challenge and came up with the following.
I created a custom subclass, inheriting from
CheckedListBox
in order to override the
Sort()
-method.
I copied the items in the
CheckedItems
-collection into a
List<object>
and the un-checked items into another
List<object>
by taking all items and excluding the checked items.
The "sub-sorting" within the checked- and unchecked regions is then done by calling
Sort()
on each of those Lists; alphabetical by default. This method has some overloads that allow you to specify a custom Comparer. If you want to sort differently, you would have to extend the code there.
After sorting the Lists, both are iterated and the indices of the
Items
-Collection are overwritten with the now sorted items, while calling
SetItemChecked(..)
with true/false (because the
CheckedListBox
has two separate collections to store the items and their checked-state and these aren't associated automatically).
Because
SetItemChecked(..)
calls
OnItemCheck(..)
in order to raise the
ItemCheck
-event, I used a boolean flag
SortingInProgress
to suppress that event while sorting.
Because
Sort()
is a protected method, I also implemented a
SortNow()
-method to be able to sort the items whenever you like.
VB.NET :
Public Class SortByCheckedListBox
Inherits CheckedListBox
Private SortingInProgress As Boolean
Public Sub New()
MyBase.New()
End Sub
Public Sub SortNow()
Sort()
End Sub
Protected Overrides Sub OnItemCheck(ice As ItemCheckEventArgs)
If Not SortingInProgress Then
MyBase.OnItemCheck(ice)
End If
End Sub
Protected Overrides Sub Sort()
If Items.Count > 1 Then
SortingInProgress = True
Dim checkedItems1 As New List(Of Object)(CheckedItems.OfType(Of Object)())
Dim uncheckedItems As New List(Of Object)(Items.OfType(Of Object)().Except(checkedItems1))
checkedItems1.Sort()
uncheckedItems.Sort()
Dim item As Integer = 0
For checkd As Integer = 0 To checkedItems1.Count - 1
Items(item) = checkedItems1(checkd)
SetItemChecked(item, True)
item += 1
Next
For uncheckd As Integer = 0 To uncheckedItems.Count - 1
Items(item) = uncheckedItems(uncheckd)
SetItemChecked(item, False)
item += 1
Next
SortingInProgress = False
End If
End Sub
End Class
C# :
public class SortByCheckedListBox : CheckedListBox
{
private bool SortingInProgress;
public SortByCheckedListBox()
: base()
{ }
public void SortNow()
{
Sort();
}
protected override void OnItemCheck(ItemCheckEventArgs ice)
{
if (!SortingInProgress)
base.OnItemCheck(ice);
}
protected override void Sort()
{
if (Items.Count > 1)
{
SortingInProgress = true;
List<object> checkedItems = new List<object>(CheckedItems.OfType<object>());
List<object> uncheckedItems = new List<object>(Items.OfType<object>().Except(checkedItems));
checkedItems.Sort();
uncheckedItems.Sort();
int item = 0;
for (int checkd = 0; checkd < checkedItems.Count; checkd++, item++)
{
Items[item] = checkedItems[checkd];
SetItemChecked(item, true);
}
for (int uncheckd = 0; uncheckd < uncheckedItems.Count; uncheckd++, item++)
{
Items[item] = uncheckedItems[uncheckd];
SetItemChecked(item, false);
}
SortingInProgress = false;
}
}
}