/ILSpy/Controls/SortableGridViewColumn.cs

http://github.com/icsharpcode/ILSpy · C# · 237 lines · 177 code · 29 blank · 31 comment · 45 complexity · fd5d8868528314042152208950230201 MD5 · raw file

  1. // Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a copy of this
  4. // software and associated documentation files (the "Software"), to deal in the Software
  5. // without restriction, including without limitation the rights to use, copy, modify, merge,
  6. // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
  7. // to whom the Software is furnished to do so, subject to the following conditions:
  8. //
  9. // The above copyright notice and this permission notice shall be included in all copies or
  10. // substantial portions of the Software.
  11. //
  12. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
  13. // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  14. // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
  15. // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  16. // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  17. // DEALINGS IN THE SOFTWARE.
  18. using System;
  19. using System.ComponentModel;
  20. using System.Windows;
  21. using System.Windows.Controls;
  22. using System.Windows.Data;
  23. namespace ICSharpCode.ILSpy.Controls
  24. {
  25. /// <summary>
  26. /// Allows to automatically sort a grid view.
  27. /// </summary>
  28. public class SortableGridViewColumn : GridViewColumn
  29. {
  30. // This class was copied from ICSharpCode.Core.Presentation.
  31. static readonly ComponentResourceKey headerTemplateKey = new ComponentResourceKey(typeof(SortableGridViewColumn), "ColumnHeaderTemplate");
  32. public SortableGridViewColumn()
  33. {
  34. this.SetValueToExtension(HeaderTemplateProperty, new DynamicResourceExtension(headerTemplateKey));
  35. }
  36. string sortBy;
  37. public string SortBy {
  38. get { return sortBy; }
  39. set {
  40. if (sortBy != value) {
  41. sortBy = value;
  42. OnPropertyChanged(new PropertyChangedEventArgs("SortBy"));
  43. }
  44. }
  45. }
  46. #region SortDirection property
  47. public static readonly DependencyProperty SortDirectionProperty =
  48. DependencyProperty.RegisterAttached("SortDirection", typeof(ColumnSortDirection), typeof(SortableGridViewColumn),
  49. new FrameworkPropertyMetadata(ColumnSortDirection.None, OnSortDirectionChanged));
  50. public ColumnSortDirection SortDirection {
  51. get { return (ColumnSortDirection)GetValue(SortDirectionProperty); }
  52. set { SetValue(SortDirectionProperty, value); }
  53. }
  54. public static ColumnSortDirection GetSortDirection(ListView listView)
  55. {
  56. return (ColumnSortDirection)listView.GetValue(SortDirectionProperty);
  57. }
  58. public static void SetSortDirection(ListView listView, ColumnSortDirection value)
  59. {
  60. listView.SetValue(SortDirectionProperty, value);
  61. }
  62. static void OnSortDirectionChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
  63. {
  64. ListView grid = sender as ListView;
  65. if (grid != null) {
  66. SortableGridViewColumn col = GetCurrentSortColumn(grid);
  67. if (col != null)
  68. col.SortDirection = (ColumnSortDirection)args.NewValue;
  69. Sort(grid);
  70. }
  71. }
  72. #endregion
  73. #region CurrentSortColumn property
  74. public static readonly DependencyProperty CurrentSortColumnProperty =
  75. DependencyProperty.RegisterAttached("CurrentSortColumn", typeof(SortableGridViewColumn), typeof(SortableGridViewColumn),
  76. new FrameworkPropertyMetadata(OnCurrentSortColumnChanged));
  77. public static SortableGridViewColumn GetCurrentSortColumn(ListView listView)
  78. {
  79. return (SortableGridViewColumn)listView.GetValue(CurrentSortColumnProperty);
  80. }
  81. public static void SetCurrentSortColumn(ListView listView, SortableGridViewColumn value)
  82. {
  83. listView.SetValue(CurrentSortColumnProperty, value);
  84. }
  85. static void OnCurrentSortColumnChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
  86. {
  87. ListView grid = sender as ListView;
  88. if (grid != null) {
  89. SortableGridViewColumn oldColumn = (SortableGridViewColumn)args.OldValue;
  90. if (oldColumn != null)
  91. oldColumn.SortDirection = ColumnSortDirection.None;
  92. SortableGridViewColumn newColumn = (SortableGridViewColumn)args.NewValue;
  93. if (newColumn != null) {
  94. newColumn.SortDirection = GetSortDirection(grid);
  95. }
  96. Sort(grid);
  97. }
  98. }
  99. #endregion
  100. #region SortMode property
  101. public static readonly DependencyProperty SortModeProperty =
  102. DependencyProperty.RegisterAttached("SortMode", typeof(ListViewSortMode), typeof(SortableGridViewColumn),
  103. new FrameworkPropertyMetadata(ListViewSortMode.None, OnSortModeChanged));
  104. public static ListViewSortMode GetSortMode(ListView listView)
  105. {
  106. return (ListViewSortMode)listView.GetValue(SortModeProperty);
  107. }
  108. public static void SetSortMode(ListView listView, ListViewSortMode value)
  109. {
  110. listView.SetValue(SortModeProperty, value);
  111. }
  112. static void OnSortModeChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
  113. {
  114. ListView grid = sender as ListView;
  115. if (grid != null) {
  116. if ((ListViewSortMode)args.NewValue != ListViewSortMode.None)
  117. grid.AddHandler(GridViewColumnHeader.ClickEvent, new RoutedEventHandler(GridViewColumnHeaderClickHandler));
  118. else
  119. grid.RemoveHandler(GridViewColumnHeader.ClickEvent, new RoutedEventHandler(GridViewColumnHeaderClickHandler));
  120. }
  121. }
  122. static void GridViewColumnHeaderClickHandler(object sender, RoutedEventArgs e)
  123. {
  124. ListView grid = sender as ListView;
  125. GridViewColumnHeader headerClicked = e.OriginalSource as GridViewColumnHeader;
  126. if (grid != null && headerClicked != null && headerClicked.Role != GridViewColumnHeaderRole.Padding) {
  127. if (headerClicked.Column == GetCurrentSortColumn(grid)) {
  128. switch (GetSortDirection(grid)) {
  129. case ColumnSortDirection.None:
  130. SetSortDirection(grid, ColumnSortDirection.Ascending);
  131. break;
  132. case ColumnSortDirection.Ascending:
  133. SetSortDirection(grid, ColumnSortDirection.Descending);
  134. break;
  135. case ColumnSortDirection.Descending:
  136. SetSortDirection(grid, ColumnSortDirection.None);
  137. break;
  138. }
  139. } else {
  140. SetSortDirection(grid, ColumnSortDirection.Ascending);
  141. SetCurrentSortColumn(grid, headerClicked.Column as SortableGridViewColumn);
  142. }
  143. }
  144. }
  145. #endregion
  146. static void Sort(ListView grid)
  147. {
  148. ColumnSortDirection currentDirection = GetSortDirection(grid);
  149. SortableGridViewColumn column = GetCurrentSortColumn(grid);
  150. ICollectionView dataView = CollectionViewSource.GetDefaultView(grid.ItemsSource);
  151. if (dataView == null) return;
  152. if (column != null && GetSortMode(grid) == ListViewSortMode.Automatic && currentDirection != ColumnSortDirection.None) {
  153. string sortBy = column.SortBy;
  154. if (sortBy == null) {
  155. Binding binding = column.DisplayMemberBinding as Binding;
  156. if (binding != null && binding.Path != null) {
  157. sortBy = binding.Path.Path;
  158. }
  159. }
  160. dataView.SortDescriptions.Clear();
  161. if (sortBy != null) {
  162. ListSortDirection direction;
  163. if (currentDirection == ColumnSortDirection.Descending)
  164. direction = ListSortDirection.Descending;
  165. else
  166. direction = ListSortDirection.Ascending;
  167. dataView.SortDescriptions.Add(new SortDescription(sortBy, direction));
  168. }
  169. } else {
  170. dataView.SortDescriptions.Clear();
  171. }
  172. dataView.Refresh();
  173. }
  174. }
  175. public enum ColumnSortDirection
  176. {
  177. None,
  178. Ascending,
  179. Descending
  180. }
  181. public enum ListViewSortMode
  182. {
  183. /// <summary>
  184. /// Disable automatic sorting when sortable columns are clicked.
  185. /// </summary>
  186. None,
  187. /// <summary>
  188. /// Fully automatic sorting.
  189. /// </summary>
  190. Automatic,
  191. /// <summary>
  192. /// Automatically update SortDirection and CurrentSortColumn properties,
  193. /// but do not actually sort the data.
  194. /// </summary>
  195. HalfAutomatic
  196. }
  197. sealed class ColumnSortDirectionToVisibilityConverter : IValueConverter
  198. {
  199. public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  200. {
  201. return Equals(value, parameter) ? Visibility.Visible : Visibility.Collapsed;
  202. }
  203. public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  204. {
  205. throw new NotSupportedException();
  206. }
  207. }
  208. }