ListViewNF.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. using System.Collections;
  2. using Timer = System.Windows.Forms.Timer;
  3. namespace CustomFormControl
  4. {
  5. public partial class ListViewNF : ListView
  6. {
  7. public class ListViewColumnSorter : IComparer
  8. {
  9. private int _columnToSort;
  10. private SortOrder _orderOfSort;
  11. private readonly CaseInsensitiveComparer _objectCompare;
  12. public ListViewColumnSorter()
  13. {
  14. // Initialize the column to '0'
  15. _columnToSort = 0;
  16. // Initialize the sort order to 'none'
  17. _orderOfSort = SortOrder.None;
  18. // Initialize the CaseInsensitiveComparer object
  19. _objectCompare = new CaseInsensitiveComparer();
  20. }
  21. public int Compare(object x, object y)
  22. {
  23. // Cast the objects to be compared to ListViewItem objects
  24. ListViewItem listviewX = (ListViewItem)x;
  25. ListViewItem listviewY = (ListViewItem)y;
  26. // Compare the two items
  27. int compareResult = _objectCompare.Compare(listviewX.SubItems[_columnToSort].Text, listviewY.SubItems[_columnToSort].Text);
  28. // Calculate correct return value based on object comparison
  29. if (_orderOfSort == SortOrder.Ascending)
  30. {
  31. // Ascending sort is selected, return normal result of compare operation
  32. return compareResult;
  33. }
  34. if (_orderOfSort == SortOrder.Descending)
  35. {
  36. // Descending sort is selected, return negative result of compare operation
  37. return (-compareResult);
  38. }
  39. // Return '0' to indicate they are equal
  40. return 0;
  41. }
  42. public int SortColumn
  43. {
  44. set => _columnToSort = value;
  45. get => _columnToSort;
  46. }
  47. public SortOrder Order
  48. {
  49. set => _orderOfSort = value;
  50. get => _orderOfSort;
  51. }
  52. }
  53. private readonly Timer _itemSelectionChangedTimer = new();
  54. private readonly Timer _selectedIndexChangedTimer = new();
  55. private ListViewItemSelectionChangedEventArgs? _itemSelectionChangedEventArgs;
  56. private EventArgs? _selectedIndexChangedEventArgs;
  57. private readonly ListViewColumnSorter _sorter;
  58. public ListViewNF()
  59. {
  60. _itemSelectionChangedTimer.Interval = 1;
  61. _selectedIndexChangedTimer.Interval = 1;
  62. _itemSelectionChangedTimer.Tick += (_, e) =>
  63. {
  64. OnItemSelectionChanged(e: _itemSelectionChangedEventArgs);
  65. _itemSelectionChangedEventArgs = null;
  66. };
  67. _selectedIndexChangedTimer.Tick += (_, e) =>
  68. {
  69. OnSelectedIndexChanged(e: _selectedIndexChangedEventArgs);
  70. _selectedIndexChangedEventArgs = null;
  71. };
  72. //Activate double buffering
  73. SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
  74. //Enable the OnNotifyMessage event so we get a chance to filter out
  75. // Windows messages before they get to the form's WndProc
  76. SetStyle(ControlStyles.EnableNotifyMessage, true);
  77. _sorter = new ListViewColumnSorter();
  78. ListViewItemSorter = _sorter;
  79. ColumnClick += ListViewNF_ColumnClick;
  80. }
  81. void ListViewNF_ColumnClick(object sender, ColumnClickEventArgs e)
  82. {
  83. if (e.Column == _sorter.SortColumn)
  84. {
  85. _sorter.Order = _sorter.Order == SortOrder.Ascending ? SortOrder.Descending : SortOrder.Ascending;
  86. }
  87. else
  88. {
  89. _sorter.SortColumn = e.Column;
  90. _sorter.Order = SortOrder.Ascending;
  91. }
  92. Sort();
  93. }
  94. protected override void OnNotifyMessage(Message m)
  95. {
  96. //Filter out the WM_ERASEBKGND message
  97. if (m.Msg != 0x14)
  98. {
  99. base.OnNotifyMessage(m);
  100. }
  101. }
  102. protected override void OnItemSelectionChanged(ListViewItemSelectionChangedEventArgs e)
  103. {
  104. if (_itemSelectionChangedTimer.Enabled)
  105. {
  106. _itemSelectionChangedTimer.Stop();
  107. base.OnItemSelectionChanged(e);
  108. }
  109. else
  110. {
  111. _itemSelectionChangedEventArgs = e;
  112. _itemSelectionChangedTimer.Start();
  113. }
  114. }
  115. protected override void OnSelectedIndexChanged(EventArgs e)
  116. {
  117. if (_selectedIndexChangedTimer.Enabled)
  118. {
  119. _selectedIndexChangedTimer.Stop();
  120. base.OnSelectedIndexChanged(e);
  121. }
  122. else
  123. {
  124. _selectedIndexChangedEventArgs = e;
  125. _selectedIndexChangedTimer.Start();
  126. }
  127. }
  128. }
  129. }