PageRenderTime 302ms CodeModel.GetById 6ms RepoModel.GetById 0ms app.codeStats 0ms

/3.2 Beta/Schedulr/JelleDruyts.Windows/DragDrop/ItemsControlExtensions.cs

#
C# | 312 lines | 249 code | 34 blank | 29 comment | 54 complexity | 568ae1d73198e4e75f9632c869d88c95 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Reflection;
  6. using System.Windows;
  7. using System.Windows.Controls;
  8. using System.Windows.Controls.Primitives;
  9. using System.Windows.Media;
  10. namespace JelleDruyts.Windows.DragDrop
  11. {
  12. internal static class ItemsControlExtensions
  13. {
  14. public static bool CanSelectMultipleItems(this ItemsControl itemsControl)
  15. {
  16. if (itemsControl is MultiSelector)
  17. {
  18. // The CanSelectMultipleItems property is protected. Use reflection to
  19. // get its value anyway.
  20. return (bool)itemsControl.GetType()
  21. .GetProperty("CanSelectMultipleItems", BindingFlags.Instance | BindingFlags.NonPublic)
  22. .GetValue(itemsControl, null);
  23. }
  24. else if (itemsControl is ListBox)
  25. {
  26. return ((ListBox)itemsControl).SelectionMode != SelectionMode.Single;
  27. }
  28. else
  29. {
  30. return false;
  31. }
  32. }
  33. public static UIElement GetItemContainer(this ItemsControl itemsControl, UIElement child)
  34. {
  35. Type itemType = GetItemContainerType(itemsControl);
  36. if (itemType != null)
  37. {
  38. return (UIElement)child.GetVisualAncestor(itemType);
  39. }
  40. return null;
  41. }
  42. public static UIElement GetItemContainerAt(this ItemsControl itemsControl, Point position)
  43. {
  44. IInputElement inputElement = itemsControl.InputHitTest(position);
  45. UIElement uiElement = inputElement as UIElement;
  46. if (uiElement != null)
  47. {
  48. return GetItemContainer(itemsControl, uiElement);
  49. }
  50. return null;
  51. }
  52. public static UIElement GetItemContainerAt(this ItemsControl itemsControl, Point position,
  53. Orientation searchDirection)
  54. {
  55. Type itemContainerType = GetItemContainerType(itemsControl);
  56. if (itemContainerType != null)
  57. {
  58. LineGeometry line;
  59. switch (searchDirection)
  60. {
  61. case Orientation.Horizontal:
  62. line = new LineGeometry(new Point(0, position.Y), new Point(itemsControl.RenderSize.Width, position.Y));
  63. break;
  64. case Orientation.Vertical:
  65. line = new LineGeometry(new Point(position.X, 0), new Point(position.X, itemsControl.RenderSize.Height));
  66. break;
  67. default:
  68. throw new ArgumentException("Invalid value for searchDirection");
  69. }
  70. List<DependencyObject> hits = new List<DependencyObject>();
  71. VisualTreeHelper.HitTest(itemsControl, null,
  72. result =>
  73. {
  74. DependencyObject itemContainer = result.VisualHit.GetVisualAncestor(itemContainerType);
  75. if (itemContainer != null) hits.Add(itemContainer);
  76. return HitTestResultBehavior.Continue;
  77. },
  78. new GeometryHitTestParameters(line));
  79. return GetClosest(itemsControl, hits, position, searchDirection);
  80. }
  81. return null;
  82. }
  83. public static Type GetItemContainerType(this ItemsControl itemsControl)
  84. {
  85. // There is no safe way to get the item container type for an ItemsControl.
  86. // First hard-code the types for the common ItemsControls.
  87. if (itemsControl is ListView)
  88. {
  89. return typeof(ListViewItem);
  90. }
  91. else if (itemsControl is TreeView)
  92. {
  93. return typeof(TreeViewItem);
  94. }
  95. else if (itemsControl is ListBox)
  96. {
  97. return typeof(ListBoxItem);
  98. }
  99. // Otherwise look for the control's ItemsPresenter, get it's child panel and the first
  100. // child of that *should* be an item container.
  101. //
  102. // If the control currently has no items, we're out of luck.
  103. if (itemsControl.Items.Count > 0)
  104. {
  105. IEnumerable<ItemsPresenter> itemsPresenters = itemsControl.GetVisualDescendents<ItemsPresenter>();
  106. foreach (ItemsPresenter itemsPresenter in itemsPresenters)
  107. {
  108. DependencyObject panel = VisualTreeHelper.GetChild(itemsPresenter, 0);
  109. DependencyObject itemContainer = VisualTreeHelper.GetChild(panel, 0);
  110. // Ensure that this actually *is* an item container by checking it with
  111. // ItemContainerGenerator.
  112. if (itemContainer != null &&
  113. itemsControl.ItemContainerGenerator.IndexFromContainer(itemContainer) != -1)
  114. {
  115. return itemContainer.GetType();
  116. }
  117. }
  118. }
  119. return null;
  120. }
  121. // [jelled] Changed GetItemsPanelOrientation to look from the bottom element up instead of top-down (to support groups).
  122. public static Orientation GetItemsPanelOrientation(this UIElement item)
  123. {
  124. ItemsPresenter itemsPresenter = item.GetVisualAncestor<ItemsPresenter>();
  125. if (itemsPresenter != null)
  126. {
  127. DependencyObject itemsPanel = VisualTreeHelper.GetChild(itemsPresenter, 0);
  128. PropertyInfo orientationProperty = itemsPanel.GetType().GetProperty("Orientation", typeof(Orientation));
  129. if (orientationProperty != null)
  130. {
  131. return (Orientation)orientationProperty.GetValue(itemsPanel, null);
  132. }
  133. }
  134. // Make a guess!
  135. return Orientation.Vertical;
  136. }
  137. //public static Orientation GetItemsPanelOrientation(this ItemsControl itemsControl)
  138. //{
  139. // ItemsPresenter itemsPresenter = itemsControl.GetVisualDescendent<ItemsPresenter>();
  140. // DependencyObject itemsPanel = VisualTreeHelper.GetChild(itemsPresenter, 0);
  141. // PropertyInfo orientationProperty = itemsPanel.GetType().GetProperty("Orientation", typeof(Orientation));
  142. // if (orientationProperty != null)
  143. // {
  144. // return (Orientation)orientationProperty.GetValue(itemsPanel, null);
  145. // }
  146. // else
  147. // {
  148. // // Make a guess!
  149. // return Orientation.Vertical;
  150. // }
  151. //}
  152. public static void SetSelectedItem(this ItemsControl itemsControl, object item)
  153. {
  154. if (itemsControl is MultiSelector)
  155. {
  156. ((MultiSelector)itemsControl).SelectedItem = null;
  157. ((MultiSelector)itemsControl).SelectedItem = item;
  158. }
  159. else if (itemsControl is ListBox)
  160. {
  161. ((ListBox)itemsControl).SelectedItem = null;
  162. ((ListBox)itemsControl).SelectedItem = item;
  163. }
  164. else if (itemsControl is TreeView)
  165. {
  166. // TO DO: Select the TreeViewItem
  167. //((TreeView)itemsControl)
  168. }
  169. else if (itemsControl is Selector)
  170. {
  171. ((Selector)itemsControl).SelectedItem = null;
  172. ((Selector)itemsControl).SelectedItem = item;
  173. }
  174. }
  175. public static IEnumerable GetSelectedItems(this ItemsControl itemsControl)
  176. {
  177. if (itemsControl is MultiSelector)
  178. {
  179. return ((MultiSelector)itemsControl).SelectedItems;
  180. }
  181. else if (itemsControl is ListBox)
  182. {
  183. ListBox listBox = (ListBox)itemsControl;
  184. if (listBox.SelectionMode == SelectionMode.Single)
  185. {
  186. return Enumerable.Repeat(listBox.SelectedItem, 1);
  187. }
  188. else
  189. {
  190. return listBox.SelectedItems;
  191. }
  192. }
  193. else if (itemsControl is TreeView)
  194. {
  195. return Enumerable.Repeat(((TreeView)itemsControl).SelectedItem, 1);
  196. }
  197. else if (itemsControl is Selector)
  198. {
  199. return Enumerable.Repeat(((Selector)itemsControl).SelectedItem, 1);
  200. }
  201. else
  202. {
  203. return Enumerable.Empty<object>();
  204. }
  205. }
  206. public static void SetItemSelected(this ItemsControl itemsControl, object item, bool value)
  207. {
  208. if (itemsControl is MultiSelector)
  209. {
  210. MultiSelector multiSelector = (MultiSelector)itemsControl;
  211. if (value)
  212. {
  213. if (multiSelector.CanSelectMultipleItems())
  214. {
  215. multiSelector.SelectedItems.Add(item);
  216. }
  217. else
  218. {
  219. multiSelector.SelectedItem = item;
  220. }
  221. }
  222. else
  223. {
  224. multiSelector.SelectedItems.Remove(item);
  225. }
  226. }
  227. else if (itemsControl is ListBox)
  228. {
  229. ListBox listBox = (ListBox)itemsControl;
  230. if (value)
  231. {
  232. if (listBox.SelectionMode != SelectionMode.Single)
  233. {
  234. listBox.SelectedItems.Add(item);
  235. }
  236. else
  237. {
  238. listBox.SelectedItem = item;
  239. }
  240. }
  241. else
  242. {
  243. listBox.SelectedItems.Remove(item);
  244. }
  245. }
  246. }
  247. static UIElement GetClosest(ItemsControl itemsControl, List<DependencyObject> items,
  248. Point position, Orientation searchDirection)
  249. {
  250. UIElement closest = null;
  251. double closestDistance = double.MaxValue;
  252. foreach (DependencyObject i in items)
  253. {
  254. UIElement uiElement = i as UIElement;
  255. if (uiElement != null)
  256. {
  257. Point p = uiElement.TransformToAncestor(itemsControl).Transform(new Point(0, 0));
  258. double distance = double.MaxValue;
  259. switch (searchDirection)
  260. {
  261. case Orientation.Horizontal:
  262. distance = Math.Abs(position.X - p.X);
  263. break;
  264. case Orientation.Vertical:
  265. distance = Math.Abs(position.Y - p.Y);
  266. break;
  267. }
  268. if (distance < closestDistance)
  269. {
  270. closest = uiElement;
  271. closestDistance = distance;
  272. }
  273. }
  274. }
  275. return closest;
  276. }
  277. }
  278. }