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

Reply via email to