Hi,
I've attached a patch that fixes some issues in the way sorting was
implemented for ListView.
All changes are accompanied by unit tests that pass in Mono 1.0/2.0 and
MS.NET 1.1/2.0.
I made my changes bug-compatible with MS as I think it's the only way to
ensure our implementations keep matching non-bug changes in MS.NET in
the near future. But this is just my opinion. Of course there are limits
to this bug-compatibility, but in this case they don't cause much harm.
The bugs I came across in MS.NET are:
- .NET 1.1: once set, modifying Sorting does not have any effect for
SmallIcon and LargeIcon views unless a custom IComparer is set. This is
fixed in .NET 2.0.
- .NET 2.0: setting Sorting to None also discards the custom IComparer,
if set.
Is it ok to send patches to this list or should they go to the
devel-list ?
If you want me to submit a bug report (with repro), just let me know.
Gert
PS. Don't be alarmed by the size of the patch, most of it are unit
tests ;-)
Index: Test/System.Windows.Forms/ChangeLog
===================================================================
--- Test/System.Windows.Forms/ChangeLog (revision 64514)
+++ Test/System.Windows.Forms/ChangeLog (working copy)
@@ -1,3 +1,8 @@
+2006-08-29 Gert Driesen <[EMAIL PROTECTED]>
+
+ * ListViewTest.cs: Added test for bug #79076. Added tests for
+ sorting bug fixes.
+
2006-08-21 Carlos Alberto Cortez <[EMAIL PROTECTED]>
* ComboBoxTest.cs: Add tests for CB.ObjectCollection
Index: Test/System.Windows.Forms/ListViewTest.cs
===================================================================
--- Test/System.Windows.Forms/ListViewTest.cs (revision 64514)
+++ Test/System.Windows.Forms/ListViewTest.cs (working copy)
@@ -8,9 +8,11 @@
//
using System;
-using System.Windows.Forms;
+using System.Collections;
using System.Drawing;
using System.Reflection;
+using System.Windows.Forms;
+
using NUnit.Framework;
namespace MonoTests.System.Windows.Forms
@@ -80,10 +82,10 @@
myform.Controls.Add (mylistview);
mylistview.BeginUpdate ();
for(int x = 1 ; x < 5000 ; x++){
- mylistview.Items.Add ("Item " + x.ToString());
+ mylistview.Items.Add ("Item " + x.ToString());
}
mylistview.EndUpdate ();
- }
+ }
[Test]
public void ClearTest ()
@@ -112,7 +114,7 @@
myform.Controls.Add (mylistview);
mylistview.BeginUpdate ();
for(int x = 1 ; x < 5000 ; x++) {
- mylistview.Items.Add ("Item " + x.ToString());
+ mylistview.Items.Add ("Item " + x.ToString());
}
mylistview.EndUpdate ();
mylistview.EnsureVisible (4999);
@@ -132,5 +134,1120 @@
Assert.IsTrue (r.Height > 0, "#35e");
Assert.IsTrue (r.Width > 0, "#35f");
}
+
+ [Test]
+ public void bug79076 ()
+ {
+ ListView entryList = new ListView ();
+ entryList.Sorting = SortOrder.Descending;
+
+ entryList.BeginUpdate ();
+ entryList.Columns.Add ("Type", 100, HorizontalAlignment.Left);
+
+ ListViewItem item = new ListViewItem (new string [] { "A" });
+ entryList.Items.Add (item);
+ item = new ListViewItem (new string [] { "B" });
+ entryList.Items.Add (item);
+ }
+
+ [Test]
+ public void Sort_Details_NotCreated ()
+ {
+ AssertSortNoIcon_NotCreated (View.Details);
+ }
+
+ [Test]
+ public void Sort_Details_Created ()
+ {
+ AssertSortNoIcon_Created (View.Details);
+ }
+
+ [Test]
+ public void Sort_LargeIcon_Created ()
+ {
+ AssertSortIcon_Created (View.LargeIcon);
+ }
+
+ [Test]
+ public void Sort_LargeIcon_NotCreated ()
+ {
+ AssertSortIcon_NotCreated (View.LargeIcon);
+ }
+
+ [Test]
+ public void Sort_List_NotCreated ()
+ {
+ AssertSortNoIcon_NotCreated (View.List);
+ }
+
+ [Test]
+ public void Sort_List_Created ()
+ {
+ AssertSortNoIcon_Created (View.List);
+ }
+
+ [Test]
+ public void Sort_SmallIcon_Created ()
+ {
+ AssertSortIcon_Created (View.SmallIcon);
+ }
+
+ [Test]
+ public void Sort_SmallIcon_NotCreated ()
+ {
+ AssertSortIcon_NotCreated (View.SmallIcon);
+ }
+
+#if NET_2_0
+ [Test]
+ public void Sort_Tile_Created ()
+ {
+ AssertSortNoIcon_Created (View.Tile);
+ }
+
+ [Test]
+ public void Sort_Tile_NotCreated ()
+ {
+ AssertSortNoIcon_NotCreated (View.Tile);
+ }
+#endif
+
+ private void AssertSortIcon_Created (View view)
+ {
+ int compareCount = 0;
+
+ Form form = new Form ();
+ ListView lvw = CreateListView (view);
+ form.Controls.Add (lvw);
+ Assert.IsNull (lvw.ListViewItemSorter, "#A");
+
+ form.Show ();
+
+ Assert.IsNull (lvw.ListViewItemSorter, "#B1");
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#B2");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#B3");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#B4");
+
+ lvw.Sorting = SortOrder.None;
+ Assert.IsNull (lvw.ListViewItemSorter, "#C1");
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#C2");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#C3");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#C4");
+
+ lvw.Sorting = SortOrder.Descending;
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#D1");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#D2");
+ Assert.AreEqual ("B", lvw.Items [1].Text, "#D3");
+ Assert.AreEqual ("A", lvw.Items [2].Text, "#D4");
+
+ lvw.Sorting = SortOrder.Ascending;
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#E1");
+#if NET_2_0
+ Assert.AreEqual ("A", lvw.Items [0].Text, "#E2");
+ Assert.AreEqual ("B", lvw.Items [1].Text, "#E3");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#E4");
+#else
+ // in .NET 1.1, changing Sorting does not have any effect for
+ // SmallIcon and LargeIcon view if no custom comparer is used
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#E2");
+ Assert.AreEqual ("B", lvw.Items [1].Text, "#E3");
+ Assert.AreEqual ("A", lvw.Items [2].Text, "#E4");
+#endif
+
+ lvw.Sorting = SortOrder.None;
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#F1");
+#if NET_2_0
+ Assert.AreEqual ("A", lvw.Items [0].Text, "#F2");
+ Assert.AreEqual ("B", lvw.Items [1].Text, "#F3");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#F4");
+#else
+ // in .NET 1.1, changing Sorting does not have any effect for
+ // SmallIcon and LargeIcon view if no custom comparer is used
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#E2");
+ Assert.AreEqual ("B", lvw.Items [1].Text, "#E3");
+ Assert.AreEqual ("A", lvw.Items [2].Text, "#E4");
+#endif
+
+ lvw.Sorting = SortOrder.Ascending;
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#G1");
+#if NET_2_0
+ Assert.AreEqual ("A", lvw.Items [0].Text, "#G2");
+ Assert.AreEqual ("B", lvw.Items [1].Text, "#G3");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#G4");
+#else
+ // in .NET 1.1, changing Sorting does not have any effect for
+ // SmallIcon and LargeIcon view if no custom comparer is used
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#G2");
+ Assert.AreEqual ("B", lvw.Items [1].Text, "#G3");
+ Assert.AreEqual ("A", lvw.Items [2].Text, "#G4");
+#endif
+
+ lvw.Sorting = SortOrder.Descending;
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#G1");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#G2");
+ Assert.AreEqual ("B", lvw.Items [1].Text, "#G3");
+ Assert.AreEqual ("A", lvw.Items [2].Text, "#G4");
+
+ lvw.Sorting = SortOrder.None;
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#H1");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#H2");
+ Assert.AreEqual ("B", lvw.Items [1].Text, "#H3");
+ Assert.AreEqual ("A", lvw.Items [2].Text, "#H4");
+
+ // when Sorting is None and a new item is added, the collection is
+ // sorted using the previous Sorting value
+ lvw.Items.Add ("BB");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#I1");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#I2");
+ Assert.AreEqual ("BB", lvw.Items [1].Text, "#I3");
+ Assert.AreEqual ("B", lvw.Items [2].Text, "#I4");
+ Assert.AreEqual ("A", lvw.Items [3].Text, "#I5");
+
+ lvw.Sorting = SortOrder.Ascending;
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#J1");
+#if NET_2_0
+ Assert.AreEqual ("A", lvw.Items [0].Text, "#J2");
+ Assert.AreEqual ("B", lvw.Items [1].Text, "#J3");
+ Assert.AreEqual ("BB", lvw.Items [2].Text, "#J4");
+ Assert.AreEqual ("C", lvw.Items [3].Text, "#J5");
+#else
+ // in .NET 1.1, changing Sorting does not have any effect for
+ // SmallIcon and LargeIcon view if no custom comparer is used
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#J2");
+ Assert.AreEqual ("BB", lvw.Items [1].Text, "#J3");
+ Assert.AreEqual ("B", lvw.Items [2].Text, "#J4");
+ Assert.AreEqual ("A", lvw.Items [3].Text, "#J5");
+#endif
+
+ // when Sorting is not None and a new item is added, the
+ // collection is re-sorted automatically
+ lvw.Items.Add ("BA");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#K1");
+#if NET_2_0
+ Assert.AreEqual ("A", lvw.Items [0].Text, "#K2");
+ Assert.AreEqual ("B", lvw.Items [1].Text, "#K3");
+ Assert.AreEqual ("BA", lvw.Items [2].Text, "#K4");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#K5");
+ Assert.AreEqual ("C", lvw.Items [4].Text, "#K6");
+#else
+ // in .NET 1.1, changing Sorting does not have any effect for
+ // SmallIcon and LargeIcon view if no custom comparer is used
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#K2");
+ Assert.AreEqual ("BB", lvw.Items [1].Text, "#K3");
+ Assert.AreEqual ("BA", lvw.Items [2].Text, "#K4");
+ Assert.AreEqual ("B", lvw.Items [3].Text, "#K5");
+ Assert.AreEqual ("A", lvw.Items [4].Text, "#K6");
+#endif
+
+ // assign a custom comparer
+ MockComparer mc = new MockComparer (false);
+ lvw.ListViewItemSorter = mc;
+
+ // when a custom IComparer is assigned, the collection is immediately
+ // re-sorted
+ Assert.IsTrue (mc.CompareCount > compareCount, "#L1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#L2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#L3");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#L4");
+ Assert.AreEqual ("BB", lvw.Items [1].Text, "#L5");
+ Assert.AreEqual ("BA", lvw.Items [2].Text, "#L6");
+ Assert.AreEqual ("B", lvw.Items [3].Text, "#L7");
+ Assert.AreEqual ("A", lvw.Items [4].Text, "#L8");
+
+ // record compare count
+ compareCount = mc.CompareCount;
+
+ // modifying Sorting results in re-sort
+ lvw.Sorting = SortOrder.Descending;
+ Assert.IsTrue (mc.CompareCount > compareCount, "#M1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#M2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#M3");
+ Assert.AreEqual ("A", lvw.Items [0].Text, "#M4");
+ Assert.AreEqual ("B", lvw.Items [1].Text, "#M5");
+ Assert.AreEqual ("BA", lvw.Items [2].Text, "#M6");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#M7");
+ Assert.AreEqual ("C", lvw.Items [4].Text, "#M8");
+
+ // record compare count
+ compareCount = mc.CompareCount;
+
+ // setting Sorting to the same value does not result in a sort
+ // operation
+ lvw.Sorting = SortOrder.Descending;
+ Assert.AreEqual (compareCount, mc.CompareCount, "#N1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#N2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#N3");
+ Assert.AreEqual ("A", lvw.Items [0].Text, "#N4");
+ Assert.AreEqual ("B", lvw.Items [1].Text, "#N5");
+ Assert.AreEqual ("BA", lvw.Items [2].Text, "#N6");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#N7");
+ Assert.AreEqual ("C", lvw.Items [4].Text, "#N8");
+
+ // modifying Sorting results in re-sort
+ lvw.Sorting = SortOrder.Ascending;
+ Assert.IsTrue (mc.CompareCount > compareCount, "#O1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#O2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#O3");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#O4");
+ Assert.AreEqual ("BB", lvw.Items [1].Text, "#O5");
+ Assert.AreEqual ("BA", lvw.Items [2].Text, "#O6");
+ Assert.AreEqual ("B", lvw.Items [3].Text, "#O7");
+ Assert.AreEqual ("A", lvw.Items [4].Text, "#O8");
+
+ // record compare count
+ compareCount = mc.CompareCount;
+
+ // adding an item when Sorting is not None causes re-sort
+ lvw.Items.Add ("BC");
+ Assert.IsTrue (mc.CompareCount > compareCount, "#P1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#P2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#P3");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#P4");
+ Assert.AreEqual ("BC", lvw.Items [1].Text, "#P5");
+ Assert.AreEqual ("BB", lvw.Items [2].Text, "#P6");
+ Assert.AreEqual ("BA", lvw.Items [3].Text, "#P7");
+ Assert.AreEqual ("B", lvw.Items [4].Text, "#P8");
+ Assert.AreEqual ("A", lvw.Items [5].Text, "#P9");
+
+ // record compare count
+ compareCount = mc.CompareCount;
+
+ // assigning the same custom IComparer again does not result in a
+ // re-sort
+ lvw.ListViewItemSorter = mc;
+ Assert.AreEqual (compareCount, mc.CompareCount, "#Q1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#Q2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#Q3");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#Q4");
+ Assert.AreEqual ("BC", lvw.Items [1].Text, "#Q5");
+ Assert.AreEqual ("BB", lvw.Items [2].Text, "#Q6");
+ Assert.AreEqual ("BA", lvw.Items [3].Text, "#Q7");
+ Assert.AreEqual ("B", lvw.Items [4].Text, "#Q8");
+ Assert.AreEqual ("A", lvw.Items [5].Text, "#Q9");
+
+ // setting Sorting to None does not perform a sort
+ lvw.Sorting = SortOrder.None;
+ Assert.AreEqual (compareCount, mc.CompareCount, "#R1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#R2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#R3");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#R4");
+ Assert.AreEqual ("BC", lvw.Items [1].Text, "#R5");
+ Assert.AreEqual ("BB", lvw.Items [2].Text, "#R6");
+ Assert.AreEqual ("BA", lvw.Items [3].Text, "#R7");
+ Assert.AreEqual ("B", lvw.Items [4].Text, "#R8");
+ Assert.AreEqual ("A", lvw.Items [5].Text, "#R9");
+
+ // assigning the custom IComparer again does not result in a
+ // re-sort
+ lvw.ListViewItemSorter = mc;
+ Assert.AreEqual (compareCount, mc.CompareCount, "#S1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#S2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#S3");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#S4");
+ Assert.AreEqual ("BC", lvw.Items [1].Text, "#S5");
+ Assert.AreEqual ("BB", lvw.Items [2].Text, "#S6");
+ Assert.AreEqual ("BA", lvw.Items [3].Text, "#S7");
+ Assert.AreEqual ("B", lvw.Items [4].Text, "#S8");
+ Assert.AreEqual ("A", lvw.Items [5].Text, "#S9");
+
+ // set Sorting to Ascending again
+ lvw.Sorting = SortOrder.Ascending;
+ Assert.IsTrue (mc.CompareCount > compareCount, "#T1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#T2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#T3");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#T4");
+ Assert.AreEqual ("BC", lvw.Items [1].Text, "#T5");
+ Assert.AreEqual ("BB", lvw.Items [2].Text, "#T6");
+ Assert.AreEqual ("BA", lvw.Items [3].Text, "#T7");
+ Assert.AreEqual ("B", lvw.Items [4].Text, "#T8");
+ Assert.AreEqual ("A", lvw.Items [5].Text, "#T9");
+
+ // record compare count
+ compareCount = mc.CompareCount;
+
+ // explicitly calling Sort results in a sort operation
+ lvw.Sort ();
+ Assert.IsTrue (mc.CompareCount > compareCount, "#U1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#U2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#U3");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#U4");
+ Assert.AreEqual ("BC", lvw.Items [1].Text, "#U5");
+ Assert.AreEqual ("BB", lvw.Items [2].Text, "#U6");
+ Assert.AreEqual ("BA", lvw.Items [3].Text, "#U7");
+ Assert.AreEqual ("B", lvw.Items [4].Text, "#U8");
+ Assert.AreEqual ("A", lvw.Items [5].Text, "#U9");
+ lvw.Sorting = SortOrder.None;
+
+ // record compare count
+ compareCount = mc.CompareCount;
+
+ // adding an item when Sorting is None causes re-sort
+ lvw.Items.Add ("BD");
+ Assert.IsTrue (mc.CompareCount > compareCount, "#V1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#V2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#V3");
+ Assert.AreEqual ("A", lvw.Items [0].Text, "#V4");
+ Assert.AreEqual ("B", lvw.Items [1].Text, "#V5");
+ Assert.AreEqual ("BA", lvw.Items [2].Text, "#V6");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#V7");
+ Assert.AreEqual ("BC", lvw.Items [4].Text, "#V8");
+ Assert.AreEqual ("BD", lvw.Items [5].Text, "#V9");
+ Assert.AreEqual ("C", lvw.Items [6].Text, "#V10");
+
+ // record compare count
+ compareCount = mc.CompareCount;
+
+ // explicitly calling Sort when Sorting is None causes a re-sort
+ lvw.Sort ();
+ Assert.IsTrue (mc.CompareCount > compareCount, "#W1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#W2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#W3");
+ Assert.AreEqual ("A", lvw.Items [0].Text, "#W4");
+ Assert.AreEqual ("B", lvw.Items [1].Text, "#W5");
+ Assert.AreEqual ("BA", lvw.Items [2].Text, "#W6");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#W7");
+ Assert.AreEqual ("BC", lvw.Items [4].Text, "#W8");
+ Assert.AreEqual ("BD", lvw.Items [5].Text, "#W9");
+ Assert.AreEqual ("C", lvw.Items [6].Text, "#W10");
+
+ // record compare count
+ compareCount = mc.CompareCount;
+ }
+
+ private void AssertSortIcon_NotCreated (View view)
+ {
+ Form form = new Form ();
+ ListView lvw = CreateListView (view);
+ form.Controls.Add (lvw);
+
+ Assert.IsNull (lvw.ListViewItemSorter, "#A1");
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#A2");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#A3");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#A4");
+
+ lvw.Sorting = SortOrder.None;
+ Assert.IsNull (lvw.ListViewItemSorter, "#B1");
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#B2");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#B3");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#B4");
+
+ lvw.Sorting = SortOrder.Descending;
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#C1");
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#C2");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#C3");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#C4");
+
+ lvw.Sorting = SortOrder.Ascending;
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#D1");
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#D2");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#D3");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#D4");
+
+ // when the handle is not created and a new item is added, the new
+ // item is just appended to the collection
+ lvw.Items.Add ("BB");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#E1");
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#E2");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#E3");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#E4");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#E5");
+
+ // assign a custom comparer
+ MockComparer mc = new MockComparer (false);
+ lvw.ListViewItemSorter = mc;
+
+ // assigning a custom IComparer has no effect
+ Assert.AreEqual (0, mc.CompareCount, "#F1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#F2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#F3");
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#F4");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#F5");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#F6");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#F7");
+
+ // modifying Sorting does not result in sort operation
+ lvw.Sorting = SortOrder.Descending;
+ Assert.AreEqual (0, mc.CompareCount, "#G1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#G2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#G3");
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#G4");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#G5");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#G6");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#G7");
+
+ // setting Sorting to the same value does not result in a sort
+ // operation
+ lvw.Sorting = SortOrder.Descending;
+ Assert.AreEqual (0, mc.CompareCount, "#H1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#H2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#H3");
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#H4");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#H5");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#H6");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#H7");
+
+ // setting Sorting to None does not result in a sort operation
+ lvw.Sorting = SortOrder.None;
+ Assert.AreEqual (0, mc.CompareCount, "#I1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#I2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#I3");
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#I4");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#I5");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#I6");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#I7");
+
+ // explicitly calling Sort when Sorting is None does not result
+ // in a sort operation
+ lvw.Sort ();
+ Assert.AreEqual (0, mc.CompareCount, "#J1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#J2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#J3");
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#J4");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#J5");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#J6");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#J7");
+
+ // setting Sorting again does not result in a sort operation
+ lvw.Sorting = SortOrder.Ascending;
+ Assert.AreEqual (0, mc.CompareCount, "#K1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#K2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#K3");
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#K4");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#K5");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#K6");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#K7");
+
+ // explicitly calling Sort when Sorting is Ascending does not
+ // result in a sort operation
+ lvw.Sort ();
+ Assert.AreEqual (0, mc.CompareCount, "#L1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#L2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#L3");
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#L4");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#L5");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#L6");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#L7");
+
+ // show the form to create the handle
+ form.Show ();
+
+ // when the handle is created, the items are immediately sorted
+ Assert.IsTrue (mc.CompareCount > 0, "#L1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#M2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#M3");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#M4");
+ Assert.AreEqual ("BB", lvw.Items [1].Text, "#M5");
+ Assert.AreEqual ("B", lvw.Items [2].Text, "#M6");
+ Assert.AreEqual ("A", lvw.Items [3].Text, "#M7");
+
+ // setting ListViewItemSorter to null does not result in sort
+ // operation
+ lvw.ListViewItemSorter = null;
+ Assert.IsNull (lvw.ListViewItemSorter, "#N1");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#N2");
+ Assert.AreEqual ("BB", lvw.Items [1].Text, "#N3");
+ Assert.AreEqual ("B", lvw.Items [2].Text, "#N4");
+ Assert.AreEqual ("A", lvw.Items [3].Text, "#N5");
+
+ // explicitly calling sort does not result in sort operation
+ lvw.Sort ();
+ Assert.IsNull (lvw.ListViewItemSorter, "#O1");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#O2");
+ Assert.AreEqual ("BB", lvw.Items [1].Text, "#O3");
+ Assert.AreEqual ("B", lvw.Items [2].Text, "#O4");
+ Assert.AreEqual ("A", lvw.Items [3].Text, "#O5");
+ }
+
+ private void AssertSortNoIcon_Created (View view)
+ {
+ int compareCount = 0;
+
+ Form form = new Form ();
+ ListView lvw = CreateListView (view);
+ form.Controls.Add (lvw);
+ Assert.IsNull (lvw.ListViewItemSorter, "#A");
+
+ form.Show ();
+
+ Assert.IsNull (lvw.ListViewItemSorter, "#B1");
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#B2");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#B3");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#B4");
+
+ lvw.Sorting = SortOrder.None;
+ Assert.IsNull (lvw.ListViewItemSorter, "#C1");
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#C2");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#C3");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#C4");
+
+ lvw.Sorting = SortOrder.Ascending;
+ Assert.IsNull (lvw.ListViewItemSorter, "#D1");
+ Assert.AreEqual ("A", lvw.Items [0].Text, "#D2");
+ Assert.AreEqual ("B", lvw.Items [1].Text, "#D3");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#D4");
+
+ lvw.Sorting = SortOrder.Descending;
+ Assert.IsNull (lvw.ListViewItemSorter, "#E1");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#E2");
+ Assert.AreEqual ("B", lvw.Items [1].Text, "#E3");
+ Assert.AreEqual ("A", lvw.Items [2].Text, "#E4");
+
+ lvw.Sorting = SortOrder.None;
+ Assert.IsNull (lvw.ListViewItemSorter, "#F1");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#F2");
+ Assert.AreEqual ("B", lvw.Items [1].Text, "#F3");
+ Assert.AreEqual ("A", lvw.Items [2].Text, "#F4");
+
+ // when Sorting is None and a new item is added, the item is
+ // appended to the collection
+ lvw.Items.Add ("BB");
+ Assert.IsNull (lvw.ListViewItemSorter, "#G1");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#G2");
+ Assert.AreEqual ("B", lvw.Items [1].Text, "#G3");
+ Assert.AreEqual ("A", lvw.Items [2].Text, "#G4");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#G5");
+
+ lvw.Sorting = SortOrder.Ascending;
+ Assert.IsNull (lvw.ListViewItemSorter, "#H1");
+ Assert.AreEqual ("A", lvw.Items [0].Text, "#H2");
+ Assert.AreEqual ("B", lvw.Items [1].Text, "#H3");
+ Assert.AreEqual ("BB", lvw.Items [2].Text, "#H4");
+ Assert.AreEqual ("C", lvw.Items [3].Text, "#H5");
+
+ // when Sorting is not None and a new item is added, the
+ // collection is re-sorted automatically
+ lvw.Items.Add ("BA");
+ Assert.IsNull (lvw.ListViewItemSorter, "#I1");
+ Assert.AreEqual ("A", lvw.Items [0].Text, "#I2");
+ Assert.AreEqual ("B", lvw.Items [1].Text, "#I3");
+ Assert.AreEqual ("BA", lvw.Items [2].Text, "#I4");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#I5");
+ Assert.AreEqual ("C", lvw.Items [4].Text, "#I6");
+
+ // assign a custom comparer
+ MockComparer mc = new MockComparer (false);
+ lvw.ListViewItemSorter = mc;
+
+ // when a custom IComparer is assigned, the collection is immediately
+ // re-sorted
+ Assert.IsTrue (mc.CompareCount > compareCount, "#J1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#J2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#J3");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#J4");
+ Assert.AreEqual ("BB", lvw.Items [1].Text, "#J5");
+ Assert.AreEqual ("BA", lvw.Items [2].Text, "#J6");
+ Assert.AreEqual ("B", lvw.Items [3].Text, "#J7");
+ Assert.AreEqual ("A", lvw.Items [4].Text, "#J8");
+
+ // record compare count
+ compareCount = mc.CompareCount;
+
+ // modifying the sort order results in a sort
+ lvw.Sorting = SortOrder.Descending;
+ Assert.IsTrue (mc.CompareCount > compareCount, "#L1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#K2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#K3");
+ Assert.AreEqual ("A", lvw.Items [0].Text, "#K4");
+ Assert.AreEqual ("B", lvw.Items [1].Text, "#K5");
+ Assert.AreEqual ("BA", lvw.Items [2].Text, "#K6");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#K7");
+ Assert.AreEqual ("C", lvw.Items [4].Text, "#K8");
+
+ // record compare count
+ compareCount = mc.CompareCount;
+
+ // set the sort order to the same value does not result in a sort
+ // operation
+ lvw.Sorting = SortOrder.Descending;
+ Assert.AreEqual (compareCount, mc.CompareCount, "#L1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#L2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#L3");
+ Assert.AreEqual ("A", lvw.Items [0].Text, "#L4");
+ Assert.AreEqual ("B", lvw.Items [1].Text, "#L5");
+ Assert.AreEqual ("BA", lvw.Items [2].Text, "#L6");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#L7");
+ Assert.AreEqual ("C", lvw.Items [4].Text, "#L8");
+
+ // modifying the sort order results in a sort
+ lvw.Sorting = SortOrder.Ascending;
+ Assert.IsTrue (mc.CompareCount > compareCount, "#M1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#M2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#M3");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#M4");
+ Assert.AreEqual ("BB", lvw.Items [1].Text, "#M5");
+ Assert.AreEqual ("BA", lvw.Items [2].Text, "#M6");
+ Assert.AreEqual ("B", lvw.Items [3].Text, "#M7");
+ Assert.AreEqual ("A", lvw.Items [4].Text, "#M8");
+
+ // record compare count
+ compareCount = mc.CompareCount;
+
+ // adding an item when Sorting is not None caused a re-sort
+ lvw.Items.Add ("BC");
+ Assert.IsTrue (mc.CompareCount > compareCount, "#N1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#N2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#N3");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#N4");
+ Assert.AreEqual ("BC", lvw.Items [1].Text, "#N5");
+ Assert.AreEqual ("BB", lvw.Items [2].Text, "#N6");
+ Assert.AreEqual ("BA", lvw.Items [3].Text, "#N7");
+ Assert.AreEqual ("B", lvw.Items [4].Text, "#N8");
+ Assert.AreEqual ("A", lvw.Items [5].Text, "#N9");
+
+ // record compare count
+ compareCount = mc.CompareCount;
+
+ // assigning the same custom IComparer again does not result in a
+ // re-sort
+ lvw.ListViewItemSorter = mc;
+ Assert.AreEqual (compareCount, mc.CompareCount, "#O1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#O2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#O3");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#O4");
+ Assert.AreEqual ("BC", lvw.Items [1].Text, "#O5");
+ Assert.AreEqual ("BB", lvw.Items [2].Text, "#O6");
+ Assert.AreEqual ("BA", lvw.Items [3].Text, "#O7");
+ Assert.AreEqual ("B", lvw.Items [4].Text, "#O8");
+ Assert.AreEqual ("A", lvw.Items [5].Text, "#O9");
+
+ // setting sort order to None does not perform a sort and resets
+ // the ListViewItemSorter
+ lvw.Sorting = SortOrder.None;
+ Assert.AreEqual (compareCount, mc.CompareCount, "#P1");
+#if NET_2_0
+ Assert.IsNull (lvw.ListViewItemSorter, "#P2");
+#else
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#P2a");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#P2b");
+#endif
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#P3");
+ Assert.AreEqual ("BC", lvw.Items [1].Text, "#P4");
+ Assert.AreEqual ("BB", lvw.Items [2].Text, "#P5");
+ Assert.AreEqual ("BA", lvw.Items [3].Text, "#P6");
+ Assert.AreEqual ("B", lvw.Items [4].Text, "#P7");
+ Assert.AreEqual ("A", lvw.Items [5].Text, "#P8");
+
+
+ lvw.ListViewItemSorter = mc;
+#if NET_2_0
+ // assigning the previous custom IComparer again results in a
+ // re-sort
+ Assert.IsTrue (mc.CompareCount > compareCount, "#Q1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#Q2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#Q3");
+ Assert.AreEqual ("A", lvw.Items [0].Text, "#Q4");
+ Assert.AreEqual ("B", lvw.Items [1].Text, "#Q5");
+ Assert.AreEqual ("BA", lvw.Items [2].Text, "#Q6");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#Q7");
+ Assert.AreEqual ("BC", lvw.Items [4].Text, "#Q8");
+ Assert.AreEqual ("C", lvw.Items [5].Text, "#Q9");
+#else
+ Assert.AreEqual (compareCount, mc.CompareCount, "#Q1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#Q2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#Q3");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#Q4");
+ Assert.AreEqual ("BC", lvw.Items [1].Text, "#Q5");
+ Assert.AreEqual ("BB", lvw.Items [2].Text, "#Q6");
+ Assert.AreEqual ("BA", lvw.Items [3].Text, "#Q7");
+ Assert.AreEqual ("B", lvw.Items [4].Text, "#Q8");
+ Assert.AreEqual ("A", lvw.Items [5].Text, "#Q9");
+#endif
+
+ // record compare count
+ compareCount = mc.CompareCount;
+
+ // set Sorting to Ascending again to verify that the internal
+ // IComparer is not used when we reset Sorting to None
+ // (as the items would then be sorted alfabetically)
+ lvw.Sorting = SortOrder.Ascending;
+ Assert.IsTrue (mc.CompareCount > compareCount, "#R1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#R2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#R3");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#R4");
+ Assert.AreEqual ("BC", lvw.Items [1].Text, "#R5");
+ Assert.AreEqual ("BB", lvw.Items [2].Text, "#R6");
+ Assert.AreEqual ("BA", lvw.Items [3].Text, "#R7");
+ Assert.AreEqual ("B", lvw.Items [4].Text, "#R8");
+ Assert.AreEqual ("A", lvw.Items [5].Text, "#R9");
+
+ // record compare count
+ compareCount = mc.CompareCount;
+
+ lvw.Sorting = SortOrder.None;
+ Assert.AreEqual (compareCount, mc.CompareCount, "#S1");
+#if NET_2_0
+ Assert.IsNull (lvw.ListViewItemSorter, "#S2");
+#else
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#S2a");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#S2b");
+#endif
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#S3");
+ Assert.AreEqual ("BC", lvw.Items [1].Text, "#S4");
+ Assert.AreEqual ("BB", lvw.Items [2].Text, "#S5");
+ Assert.AreEqual ("BA", lvw.Items [3].Text, "#S6");
+ Assert.AreEqual ("B", lvw.Items [4].Text, "#S7");
+ Assert.AreEqual ("A", lvw.Items [5].Text, "#S8");
+
+ // record compare count
+ compareCount = mc.CompareCount;
+
+ lvw.Items.Add ("BD");
+#if NET_2_0
+ // adding an item when Sorting is None does not cause a re-sort
+ Assert.AreEqual (compareCount, mc.CompareCount, "#T1");
+ Assert.IsNull (lvw.ListViewItemSorter, "#T2");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#T3");
+ Assert.AreEqual ("BC", lvw.Items [1].Text, "#T4");
+ Assert.AreEqual ("BB", lvw.Items [2].Text, "#T5");
+ Assert.AreEqual ("BA", lvw.Items [3].Text, "#T6");
+ Assert.AreEqual ("B", lvw.Items [4].Text, "#T7");
+ Assert.AreEqual ("A", lvw.Items [5].Text, "#T8");
+ Assert.AreEqual ("BD", lvw.Items [6].Text, "#T9");
+#else
+ // adding an item when Sorting is None results in a re-sort
+ Assert.IsTrue (mc.CompareCount > compareCount, "#T1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#T2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#T3");
+ Assert.AreEqual ("A", lvw.Items [0].Text, "#T4");
+ Assert.AreEqual ("B", lvw.Items [1].Text, "#T5");
+ Assert.AreEqual ("BA", lvw.Items [2].Text, "#T6");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#T7");
+ Assert.AreEqual ("BC", lvw.Items [4].Text, "#T8");
+ Assert.AreEqual ("BD", lvw.Items [5].Text, "#T9");
+ Assert.AreEqual ("C", lvw.Items [6].Text, "#T10");
+#endif
+
+ // record compare count
+ compareCount = mc.CompareCount;
+
+ lvw.Sort ();
+#if NET_2_0
+ // explicitly calling Sort when Sorting is None does nothing
+ Assert.AreEqual (compareCount, mc.CompareCount, "#U1");
+ Assert.IsNull (lvw.ListViewItemSorter, "#U2");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#U3");
+ Assert.AreEqual ("BC", lvw.Items [1].Text, "#U4");
+ Assert.AreEqual ("BB", lvw.Items [2].Text, "#U5");
+ Assert.AreEqual ("BA", lvw.Items [3].Text, "#U6");
+ Assert.AreEqual ("B", lvw.Items [4].Text, "#U7");
+ Assert.AreEqual ("A", lvw.Items [5].Text, "#U8");
+ Assert.AreEqual ("BD", lvw.Items [6].Text, "#U9");
+#else
+ // explicitly calling Sort when Sorting is None results in a re-sort
+ Assert.IsTrue (mc.CompareCount > compareCount, "#U1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#U2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#U3");
+ Assert.AreEqual ("A", lvw.Items [0].Text, "#U4");
+ Assert.AreEqual ("B", lvw.Items [1].Text, "#U5");
+ Assert.AreEqual ("BA", lvw.Items [2].Text, "#U6");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#U7");
+ Assert.AreEqual ("BC", lvw.Items [4].Text, "#U8");
+ Assert.AreEqual ("BD", lvw.Items [5].Text, "#U9");
+ Assert.AreEqual ("C", lvw.Items [6].Text, "#U10");
+#endif
+
+ // record compare count
+ compareCount = mc.CompareCount;
+
+ lvw.Sorting = SortOrder.Ascending;
+#if NET_2_0
+ // setting Sorting again, does not reinstate the custom IComparer
+ // but sorting is actually performed using an internal non-visible
+ // comparer
+ Assert.AreEqual (compareCount, mc.CompareCount, "#V1");
+ Assert.IsNull (lvw.ListViewItemSorter, "#V2");
+ Assert.AreEqual ("A", lvw.Items [0].Text, "#V3");
+ Assert.AreEqual ("B", lvw.Items [1].Text, "#V4");
+ Assert.AreEqual ("BA", lvw.Items [2].Text, "#V5");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#V6");
+ Assert.AreEqual ("BC", lvw.Items [4].Text, "#V7");
+ Assert.AreEqual ("BD", lvw.Items [5].Text, "#V8");
+ Assert.AreEqual ("C", lvw.Items [6].Text, "#V9");
+#else
+ // setting Sorting again, uses the custom IComparer to sort the items
+ Assert.IsTrue (mc.CompareCount > compareCount, "#V1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#V2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#V3");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#V4");
+ Assert.AreEqual ("BD", lvw.Items [1].Text, "#V5");
+ Assert.AreEqual ("BC", lvw.Items [2].Text, "#V6");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#V7");
+ Assert.AreEqual ("BA", lvw.Items [4].Text, "#V8");
+ Assert.AreEqual ("B", lvw.Items [5].Text, "#V9");
+ Assert.AreEqual ("A", lvw.Items [6].Text, "#V10");
+#endif
+
+ // record compare count
+ compareCount = mc.CompareCount;
+
+ lvw.Sort ();
+#if NET_2_0
+ // explicitly calling Sort, does not reinstate the custom IComparer
+ // but sorting is actually performed using an internal non-visible
+ // comparer
+ Assert.AreEqual (compareCount, mc.CompareCount, "#W1");
+ Assert.IsNull (lvw.ListViewItemSorter, "#W2");
+ Assert.AreEqual ("A", lvw.Items [0].Text, "#W3");
+ Assert.AreEqual ("B", lvw.Items [1].Text, "#W4");
+ Assert.AreEqual ("BA", lvw.Items [2].Text, "#W5");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#W6");
+ Assert.AreEqual ("BC", lvw.Items [4].Text, "#W7");
+ Assert.AreEqual ("BD", lvw.Items [5].Text, "#W8");
+ Assert.AreEqual ("C", lvw.Items [6].Text, "#W9");
+#else
+ // setting Sorting again, uses the custom IComparer to sort the items
+ Assert.IsTrue (mc.CompareCount > compareCount, "#W1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#W2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#W3");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#W4");
+ Assert.AreEqual ("BD", lvw.Items [1].Text, "#W5");
+ Assert.AreEqual ("BC", lvw.Items [2].Text, "#W6");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#W7");
+ Assert.AreEqual ("BA", lvw.Items [4].Text, "#W8");
+ Assert.AreEqual ("B", lvw.Items [5].Text, "#W9");
+ Assert.AreEqual ("A", lvw.Items [6].Text, "#W10");
+#endif
+
+ // record compare count
+ compareCount = mc.CompareCount;
+ }
+
+ private void AssertSortNoIcon_NotCreated (View view)
+ {
+ Form form = new Form ();
+ ListView lvw = CreateListView (view);
+ form.Controls.Add (lvw);
+
+ Assert.IsNull (lvw.ListViewItemSorter, "#A1");
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#A2");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#A3");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#A4");
+
+ lvw.Sorting = SortOrder.None;
+ Assert.IsNull (lvw.ListViewItemSorter, "#B1");
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#B2");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#B3");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#B4");
+
+ lvw.Sorting = SortOrder.Ascending;
+ Assert.IsNull (lvw.ListViewItemSorter, "#C1");
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#C2");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#C3");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#C4");
+
+ lvw.Sorting = SortOrder.Descending;
+ Assert.IsNull (lvw.ListViewItemSorter, "#D1");
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#D2");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#D3");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#D4");
+
+ lvw.Sorting = SortOrder.None;
+ Assert.IsNull (lvw.ListViewItemSorter, "#E1");
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#E2");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#E3");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#E4");
+
+ lvw.Sorting = SortOrder.Ascending;
+ Assert.IsNull (lvw.ListViewItemSorter, "#F1");
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#F2");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#F3");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#F4");
+
+ // when the handle is not created and a new item is added, the new
+ // item is just appended to the collection
+ lvw.Items.Add ("BB");
+ Assert.IsNull (lvw.ListViewItemSorter, "#G1");
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#G2");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#G3");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#G4");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#G5");
+
+ // assign a custom comparer
+ MockComparer mc = new MockComparer (false);
+ lvw.ListViewItemSorter = mc;
+
+ // assigning a custom IComparer has no effect
+ Assert.AreEqual (0, mc.CompareCount, "#H1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#H2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#H3");
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#H4");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#H5");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#H6");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#H7");
+
+ // modifying Sorting has no effect
+ lvw.Sorting = SortOrder.Descending;
+ Assert.AreEqual (0, mc.CompareCount, "#I1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#I2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#I3");
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#I4");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#I5");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#I6");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#I7");
+
+ // setting Sorting to the same value does not result in a sort
+ // operation
+ lvw.Sorting = SortOrder.Descending;
+ Assert.AreEqual (0, mc.CompareCount, "#J1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#J2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#J3");
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#J4");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#J5");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#J6");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#J7");
+
+ // setting Sorting to another value does not result in a sort
+ // operation
+ lvw.Sorting = SortOrder.Ascending;
+ Assert.AreEqual (0, mc.CompareCount, "#K1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#K2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#K3");
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#K4");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#K5");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#K6");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#K7");
+
+ lvw.Sorting = SortOrder.None;
+ Assert.AreEqual (0, mc.CompareCount, "#L1");
+#if NET_2_0
+ // setting Sorting to None does not perform a sort and resets the
+ // ListViewItemSorter
+ Assert.IsNull (lvw.ListViewItemSorter, "#L2");
+#else
+ // setting Sorting to None does not perform a sort
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#L2a");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#L2b");
+#endif
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#L3");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#L4");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#L5");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#L6");
+
+ // explicitly calling Sort when Sorting is None does nothing
+ lvw.Sort ();
+ Assert.AreEqual (0, mc.CompareCount, "#M1");
+#if NET_2_0
+ Assert.IsNull (lvw.ListViewItemSorter, "#M2");
+#else
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#M2a");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#M2b");
+#endif
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#M3");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#M4");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#M5");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#M6");
+
+ lvw.Sorting = SortOrder.Ascending;
+ Assert.AreEqual (0, mc.CompareCount, "#N1");
+#if NET_2_0
+ Assert.IsNull (lvw.ListViewItemSorter, "#N2");
+#else
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#N2a");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#N2b");
+#endif
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#N3");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#N4");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#N5");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#N6");
+
+ // explicitly set the custom IComparer again
+ lvw.ListViewItemSorter = mc;
+ Assert.AreEqual (0, mc.CompareCount, "#O1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#O2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#O3");
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#O4");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#O5");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#O6");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#O7");
+
+ // explicitly calling Sort when handle is not created does not
+ // result in sort operation
+ Assert.AreEqual (0, mc.CompareCount, "#P1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#P2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#P3");
+ Assert.AreEqual ("B", lvw.Items [0].Text, "#P4");
+ Assert.AreEqual ("A", lvw.Items [1].Text, "#P5");
+ Assert.AreEqual ("C", lvw.Items [2].Text, "#P6");
+ Assert.AreEqual ("BB", lvw.Items [3].Text, "#P7");
+
+ // show the form to create the handle
+ form.Show ();
+
+ // when the handle is created, the items are immediately sorted
+ Assert.IsTrue (mc.CompareCount > 0, "#Q1");
+ Assert.IsNotNull (lvw.ListViewItemSorter, "#Q2");
+ Assert.AreSame (mc, lvw.ListViewItemSorter, "#Q3");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#Q4");
+ Assert.AreEqual ("BB", lvw.Items [1].Text, "#Q5");
+ Assert.AreEqual ("B", lvw.Items [2].Text, "#Q6");
+ Assert.AreEqual ("A", lvw.Items [3].Text, "#Q7");
+
+ // setting ListViewItemSorter to null does not result in sort
+ // operation
+ lvw.ListViewItemSorter = null;
+ Assert.IsNull (lvw.ListViewItemSorter, "#R1");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#R2");
+ Assert.AreEqual ("BB", lvw.Items [1].Text, "#R3");
+ Assert.AreEqual ("B", lvw.Items [2].Text, "#R4");
+ Assert.AreEqual ("A", lvw.Items [3].Text, "#R5");
+
+ // explicitly calling sort does not result in sort operation
+ lvw.Sort ();
+ Assert.IsNull (lvw.ListViewItemSorter, "#S1");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#S2");
+ Assert.AreEqual ("BB", lvw.Items [1].Text, "#S3");
+ Assert.AreEqual ("B", lvw.Items [2].Text, "#S4");
+ Assert.AreEqual ("A", lvw.Items [3].Text, "#S5");
+
+ // modifying Sorting does not result in sort operation
+ lvw.Sorting = SortOrder.Ascending;
+ Assert.IsNull (lvw.ListViewItemSorter, "#T1");
+ Assert.AreEqual ("C", lvw.Items [0].Text, "#T2");
+ Assert.AreEqual ("BB", lvw.Items [1].Text, "#T3");
+ Assert.AreEqual ("B", lvw.Items [2].Text, "#T4");
+ Assert.AreEqual ("A", lvw.Items [3].Text, "#T5");
+ }
+
+ private ListView CreateListView (View view)
+ {
+ ListView lvw = new ListView ();
+ lvw.View = view;
+ lvw.Items.Add ("B");
+ lvw.Items.Add ("A");
+ lvw.Items.Add ("C");
+ return lvw;
+ }
+
+ private class MockComparer : IComparer
+ {
+ int _compareCount;
+ bool _throwException;
+
+ public MockComparer (bool throwException)
+ {
+ _throwException = throwException;
+ }
+
+ public int CompareCount {
+ get { return _compareCount; }
+ }
+
+ public int Compare (object x, object y)
+ {
+ _compareCount++;
+ if (_throwException)
+ throw new InvalidOperationException ();
+
+ ListViewItem item_x = x as ListViewItem;
+ ListViewItem item_y = y as ListViewItem;
+ SortOrder sortOrder = item_x.ListView.Sorting;
+
+ // we'll actually perform a reverse-sort
+ if (sortOrder == SortOrder.Ascending)
+ return String.Compare (item_y.Text, item_x.Text);
+ else
+ return String.Compare (item_x.Text, item_y.Text);
+ }
+ }
}
}
Index: System.Windows.Forms/ChangeLog
===================================================================
--- System.Windows.Forms/ChangeLog (revision 64514)
+++ System.Windows.Forms/ChangeLog (working copy)
@@ -1,3 +1,32 @@
+<<<<<<< .mine
+2006-08-29 Gert Driesen <[EMAIL PROTECTED]>
+
+ * ListView.cs: Do not initialize item_sorter in init. To match MS,
+ return null for ListViewItemSorter if View is SmallIcon or LargeIcon
+ and the internal comparer is set. When a new ListViewItemSorter is set,
+ sort the items. Use Enum.IsDefined to verify whether a valid SortOrder
+ was specified. No further processing is necessary if SortOrder is set
+ to it's current value. If Sorting is modified to None, and View is
+ neither SmallIcon nor LargeIcon then: on 2.0 profile set item_sorter
+ (either custom or our internal ItemComparer) to null, on 1.0 profile
+ only set item_sorter to null if its our internal IComparer. If Sorting
+ is modified to Ascending or Descending, then use our internal IComparer
+ if none is set, and if the current IComparer is our internal one then:
+ on 2.0 profile always replace it with one for new Sorting, and on 1.0
+ profile only use new Sorting if view is not SmallIcon or LargeIcon. Use
+ Enum.IsDefined to verify whether a valid View value is specified in
+ its setter. Automatically sort listview items when listview is
+ created. In Sort, do nothing if ListView is not yet created, or if
+ no item_sorter is set (no Sorting was set, Sorting was explicitly set
+ to None or ListViewItemSorter was set to null). Added Sort overload
+ taking a bool to indicate whether the ListView should be redrawn when
+ items are sorted (we use this in ListViewItemCollection to avoid double
+ redraws). Modified our internal IComparer to take the sort order into
+ account. In Add and AddRange methods of ListViewItemCollection, also
+ call Sort if Sorting is None (necessary for SmallIcon and LargeIcon
+ view), but use overload with noredraw option to to avoid double redraw.
+
+=======
2006-08-29 Mike Kestner <[EMAIL PROTECTED]>
* ThemeWin32Classic.cs: draw selections for columns in FullRowSelect
@@ -3,4 +32,5 @@
when SubItems.Count < Columns.Count. [Fixes #79167]
+>>>>>>> .r64514
2006-08-28 Peter Dennis Bartok <[EMAIL PROTECTED]>
Index: System.Windows.Forms/ListView.cs
===================================================================
--- System.Windows.Forms/ListView.cs (revision 64514)
+++ System.Windows.Forms/ListView.cs (working copy)
@@ -61,7 +61,7 @@
private ColumnHeaderStyle header_style = ColumnHeaderStyle.Clickable;
private bool hide_selection = true;
private bool hover_selection = false;
- private IComparer item_sorter = new ItemComparer ();
+ private IComparer item_sorter;
private ListViewItemCollection items;
private bool label_edit = false;
private bool label_wrap = true;
@@ -438,8 +438,17 @@
[Browsable (false)]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
public IComparer ListViewItemSorter {
- get { return item_sorter; }
- set { item_sorter = value; }
+ get {
+ if (View != View.SmallIcon && View != View.LargeIcon && item_sorter is ItemComparer)
+ return null;
+ return item_sorter;
+ }
+ set {
+ if (item_sorter != value) {
+ item_sorter = value;
+ Sort ();
+ }
+ }
}
[DefaultValue (true)]
@@ -496,15 +505,46 @@
public SortOrder Sorting {
get { return sort_order; }
set {
- if (value != SortOrder.Ascending && value != SortOrder.Descending &&
- value != SortOrder.None) {
- throw new InvalidEnumArgumentException (string.Format
- ("Enum argument value '{0}' is not valid for Sorting", value));
+ if (!Enum.IsDefined (typeof (SortOrder), value)) {
+ throw new InvalidEnumArgumentException ("value", (int) value,
+ typeof (SortOrder));
}
- if (sort_order != value) {
- sort_order = value;
+ if (sort_order == value)
+ return;
+
+ sort_order = value;
+
+ if (value == SortOrder.None) {
+ if (item_sorter != null) {
+ // ListViewItemSorter should never be reset for SmallIcon
+ // and LargeIcon view
+ if (View != View.SmallIcon && View != View.LargeIcon)
+#if NET_2_0
+ item_sorter = null;
+#else
+ // in .NET 1.1, only internal IComparer would be
+ // set to null
+ if (item_sorter is ItemComparer)
+ item_sorter = null;
+#endif
+ }
this.Redraw (false);
+ } else {
+ if (item_sorter == null)
+ item_sorter = new ItemComparer (value);
+ if (item_sorter is ItemComparer) {
+#if NET_2_0
+ item_sorter = new ItemComparer (value);
+#else
+ // in .NET 1.1, the sort order is not updated for
+ // SmallIcon and LargeIcon views if no custom IComparer
+ // is set
+ if (View != View.SmallIcon && View != View.LargeIcon)
+ item_sorter = new ItemComparer (value);
+#endif
+ }
+ Sort ();
}
}
}
@@ -572,12 +612,10 @@
public View View {
get { return view; }
set {
- if (value != View.Details && value != View.LargeIcon &&
- value != View.List && value != View.SmallIcon ) {
- throw new InvalidEnumArgumentException (string.Format
- ("Enum argument value '{0}' is not valid for View", value));
- }
-
+ if (!Enum.IsDefined (typeof (View), value))
+ throw new InvalidEnumArgumentException ("value", (int) value,
+ typeof (View));
+
if (view != value) {
h_scroll.Value = v_scroll.Value = 0;
view = value;
@@ -1721,6 +1759,7 @@
protected override void OnHandleCreated (EventArgs e)
{
base.OnHandleCreated (e);
+ Sort ();
}
protected override void OnHandleDestroyed (EventArgs e)
@@ -1856,13 +1895,18 @@
public void Sort ()
{
- if (sort_order != SortOrder.None)
- items.list.Sort (item_sorter);
+ Sort (true);
+ }
- if (sort_order == SortOrder.Descending)
- items.list.Reverse ();
-
- this.Redraw (true);
+ private void Sort (bool redraw)
+ {
+ if (!IsHandleCreated || item_sorter == null) {
+ return;
+ }
+
+ items.list.Sort (item_sorter);
+ if (redraw)
+ this.Redraw (true);
}
public override string ToString ()
@@ -2073,12 +2117,21 @@
}
private class ItemComparer : IComparer {
+ readonly SortOrder _sortOrder;
+ public ItemComparer (SortOrder sortOrder)
+ {
+ _sortOrder = sortOrder;
+ }
+
public int Compare (object x, object y)
{
ListViewItem item_x = x as ListViewItem;
ListViewItem item_y = y as ListViewItem;
- return String.Compare (item_x.Text, item_y.Text);
+ if (_sortOrder == SortOrder.Ascending)
+ return String.Compare (item_x.Text, item_y.Text);
+ else
+ return String.Compare (item_y.Text, item_x.Text);
}
}
@@ -2562,11 +2615,8 @@
value.Owner = owner;
list.Add (value);
- if (owner.Sorting != SortOrder.None)
- owner.Sort ();
-
+ owner.Sort (false);
owner.Redraw (true);
-
return value;
}
@@ -2595,9 +2645,7 @@
list.Add (item);
}
- if (owner.Sorting != SortOrder.None)
- owner.Sort ();
-
+ owner.Sort (false);
owner.Redraw (true);
}
_______________________________________________
Mono-winforms-list maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-winforms-list