locked
Problem with listview sorting by clicking on its header RRS feed

  • Question

  • Hello. I have a listview that can be sorted by clicking on its header. The problem is when I click on its header very quickly then the second click doesn't have any affect. I think it's because listview interprets the second click as double one (it doesn't happen if i click slowly).  For example windows explorer doesn't have this problem, we can sort its content as quickly as we want. Is there any way to solve this issue? By the way i don't change property Sorting of listView in order to prevent its recreation and i use ColumnClick event for sorting.
    • Edited by Booster1 Sunday, December 20, 2015 2:41 PM
    Sunday, December 20, 2015 2:26 PM

Answers

  • OK, I can reproduce that. Not that it's much help though.

    Because I see no easy code based fix for this.

    .

    The options I see here are:

    1) You write a bunch of code, subclass listview and intercept the double click windows message for the header, raise an extra event you can subscribe to.

    2) Change to a different technology which offers easier control re-templating ( wpf ).

    3) Investigate the various ListView replacements which are available such as http://www.componentowl.com/better-listview-express One of these may offer better support of this specific scenario. They're outside the scope of this forum though, since they're not Microsoft.

    4) Click slower.

    .

    You didn't seem to take option 4) seriously first time round.  In practice, users tend to learn how an app works by usage very quickly. If double click doesn't work then ( in my experience ) users are unlikely to even think it's an issue let alone call support.


    Hope that helps.

    Technet articles: WPF: Layout Lab; All my Technet Articles

    Monday, December 21, 2015 11:15 AM

All replies

  • You already seem to have a fix though.

    Click slower.

    My advice would be not to overcomplicate things.

    I think, also, the issue could well be that you're clicking whilst it's busy sorting already.


    Hope that helps.

    Technet articles: WPF: Layout Lab; All my Technet Articles

    Sunday, December 20, 2015 5:14 PM
  • [quote]

    You already seem to have a fix though.

    Click slower.

    My advice would be not to overcomplicate things.

    [/quote]

    You have deserved a price for useless and taunted answer. Have you understood what I wrote or not?  Look at windows explorer you can sort folders in it very quickly, it doesn't mixed up second click as double one. ColumnClick doesn't receive second click if it's a double one. I just want to force listview to handle clicks like windows explorer. Is this so hard?





    • Edited by Booster1 Sunday, December 20, 2015 6:24 PM
    Sunday, December 20, 2015 6:18 PM
  • I can't reproduce your issue.

    When I double click on a column header it sorts for me. Maybe you're clicking very very fast or something.

    I tried handling double click on the ListView.

    If I double click the header, it doesn't fire.

    There is no easily available double click on a column header event.

    You could perhaps inherit listview and extend. That doesn't look very easy to me but you can get an idea of what that would involve from this thread:

    http://stackoverflow.com/questions/5943112/how-can-i-catch-the-autosize-double-click-event-on-a-listview-in-vb-net

    My test code:

        public partial class Form1 : Form
        {
            private ListViewColumnSorter lvwColumnSorter;
            public Form1()
            {
                InitializeComponent();
                listView1.View = View.Details;
                listView1.Columns.Add("FirstName");
                listView1.Columns.Add("LastName");
                listView1.Items.Add(new ListViewItem(new[] { "Tom", "Jones" }));
                listView1.Items.Add(new ListViewItem(new[] { "Elvis", "Presley" }));
                listView1.Items.Add(new ListViewItem(new[] { "James", "Morrison" }));
                listView1.Items.Add(new ListViewItem(new[] { "Lou", "Reed" }));
                listView1.Items.Add(new ListViewItem(new[] { "Bob", "Dylan" }));
                lvwColumnSorter = new ListViewColumnSorter();
                this.listView1.ListViewItemSorter = lvwColumnSorter;
                listView1.ColumnClick += ListView1_ColumnClick;
            }
    
            private void ListView1_ColumnClick(object sender, ColumnClickEventArgs e)
            {
                // Determine if clicked column is already the column that is being sorted.
                if (e.Column == lvwColumnSorter.SortColumn)
                {
                    // Reverse the current sort direction for this column.
                    if (lvwColumnSorter.Order == SortOrder.Ascending)
                    {
                        lvwColumnSorter.Order = SortOrder.Descending;
                    }
                    else
                    {
                        lvwColumnSorter.Order = SortOrder.Ascending;
                    }
                }
                else
                {
                    // Set the column number that is to be sorted; default to ascending.
                    lvwColumnSorter.SortColumn = e.Column;
                    lvwColumnSorter.Order = SortOrder.Ascending;
                }
    
                // Perform the sort with these new sort options.
                this.listView1.Sort();
            }
            private void listView1_MouseDoubleClick(object sender, MouseEventArgs e)
            {
                Debug.WriteLine("Double !");
            }
        }

    the sorter thing is from here https://support.microsoft.com/en-gb/kb/319401:

       public class ListViewColumnSorter : IComparer
        {
            /// <summary>
            /// Specifies the column to be sorted
            /// </summary>
            private int ColumnToSort;
            /// <summary>
            /// Specifies the order in which to sort (i.e. 'Ascending').
            /// </summary>
            private SortOrder OrderOfSort;
            /// <summary>
            /// Case insensitive comparer object
            /// </summary>
            private CaseInsensitiveComparer ObjectCompare;
    
            /// <summary>
            /// Class constructor.  Initializes various elements
            /// </summary>
            public ListViewColumnSorter()
            {
                // Initialize the column to '0'
                ColumnToSort = 0;
    
                // Initialize the sort order to 'none'
                OrderOfSort = SortOrder.None;
    
                // Initialize the CaseInsensitiveComparer object
                ObjectCompare = new CaseInsensitiveComparer();
            }
    
            /// <summary>
            /// This method is inherited from the IComparer interface.  It compares the two objects passed using a case insensitive comparison.
            /// </summary>
            /// <param name="x">First object to be compared</param>
            /// <param name="y">Second object to be compared</param>
            /// <returns>The result of the comparison. "0" if equal, negative if 'x' is less than 'y' and positive if 'x' is greater than 'y'</returns>
            public int Compare(object x, object y)
            {
                int compareResult;
                ListViewItem listviewX, listviewY;
    
                // Cast the objects to be compared to ListViewItem objects
                listviewX = (ListViewItem)x;
                listviewY = (ListViewItem)y;
    
                // Compare the two items
                compareResult = ObjectCompare.Compare(listviewX.SubItems[ColumnToSort].Text, listviewY.SubItems[ColumnToSort].Text);
    
                // Calculate correct return value based on object comparison
                if (OrderOfSort == SortOrder.Ascending)
                {
                    // Ascending sort is selected, return normal result of compare operation
                    return compareResult;
                }
                else if (OrderOfSort == SortOrder.Descending)
                {
                    // Descending sort is selected, return negative result of compare operation
                    return (-compareResult);
                }
                else
                {
                    // Return '0' to indicate they are equal
                    return 0;
                }
            }
    
            /// <summary>
            /// Gets or sets the number of the column to which to apply the sorting operation (Defaults to '0').
            /// </summary>
            public int SortColumn
            {
                set
                {
                    ColumnToSort = value;
                }
                get
                {
                    return ColumnToSort;
                }
            }
    
            /// <summary>
            /// Gets or sets the order of sorting to apply (for example, 'Ascending' or 'Descending').
            /// </summary>
            public SortOrder Order
            {
                set
                {
                    OrderOfSort = value;
                }
                get
                {
                    return OrderOfSort;
                }
            }
    
        }


    Hope that helps.

    Technet articles: WPF: Layout Lab; All my Technet Articles

    Sunday, December 20, 2015 8:52 PM
  • What do you mean very very fast? I'm doing it normally but it's dblclick. I didn't say i receive dblclick event, i did say columnClick doesn't receive second click if it's double. The issue is not with sorter but with columnClick event. I've  made another test example without any sorters and the behavior is the same as i described.

    private void listView1_ColumnClick(object sender, ColumnClickEventArgs e)
            {
                ++counter;
    
                Debug.WriteLine(counter);
            }

    I see only first number counter if i do dblclick.


    • Edited by Booster1 Monday, December 21, 2015 4:31 AM
    Monday, December 21, 2015 3:50 AM
  • OK, I can reproduce that. Not that it's much help though.

    Because I see no easy code based fix for this.

    .

    The options I see here are:

    1) You write a bunch of code, subclass listview and intercept the double click windows message for the header, raise an extra event you can subscribe to.

    2) Change to a different technology which offers easier control re-templating ( wpf ).

    3) Investigate the various ListView replacements which are available such as http://www.componentowl.com/better-listview-express One of these may offer better support of this specific scenario. They're outside the scope of this forum though, since they're not Microsoft.

    4) Click slower.

    .

    You didn't seem to take option 4) seriously first time round.  In practice, users tend to learn how an app works by usage very quickly. If double click doesn't work then ( in my experience ) users are unlikely to even think it's an issue let alone call support.


    Hope that helps.

    Technet articles: WPF: Layout Lab; All my Technet Articles

    Monday, December 21, 2015 11:15 AM