Advertisement
Guest User

Untitled

a guest
Nov 26th, 2014
166
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 27.64 KB | None | 0 0
  1. public static class DragDropRowBehavior
  2. {
  3. private static DataGrid dataGrid;
  4.  
  5. private static Popup popup;
  6.  
  7. private static bool enable;
  8.  
  9. private static object draggedItem;
  10.  
  11. public static object DraggedItem
  12. {
  13. get { return DragDropRowBehavior.draggedItem; }
  14. set { DragDropRowBehavior.draggedItem = value; }
  15. }
  16.  
  17. public static Popup GetPopupControl(DependencyObject obj)
  18. {
  19. return (Popup)obj.GetValue(PopupControlProperty);
  20. }
  21.  
  22. public static void SetPopupControl(DependencyObject obj, Popup value)
  23. {
  24. obj.SetValue(PopupControlProperty, value);
  25. }
  26.  
  27. // Using a DependencyProperty as the backing store for PopupControl. This enables animation, styling, binding, etc...
  28. public static readonly DependencyProperty PopupControlProperty =
  29. DependencyProperty.RegisterAttached("PopupControl", typeof(Popup), typeof(DragDropRowBehavior), new UIPropertyMetadata(null, OnPopupControlChanged));
  30.  
  31. private static void OnPopupControlChanged(DependencyObject depObject, DependencyPropertyChangedEventArgs e)
  32. {
  33. if (e.NewValue == null || !(e.NewValue is Popup))
  34. {
  35. throw new ArgumentException("Popup Control should be set", "PopupControl");
  36. }
  37. popup = e.NewValue as Popup;
  38.  
  39. dataGrid = depObject as DataGrid;
  40. // Check if DataGrid
  41. if (dataGrid == null)
  42. return;
  43.  
  44.  
  45. if (enable && popup != null)
  46. {
  47. dataGrid.BeginningEdit += new EventHandler<DataGridBeginningEditEventArgs>(OnBeginEdit);
  48. dataGrid.CellEditEnding += new EventHandler<DataGridCellEditEndingEventArgs>(OnEndEdit);
  49. dataGrid.MouseLeftButtonUp += new System.Windows.Input.MouseButtonEventHandler(OnMouseLeftButtonUp);
  50. dataGrid.MouseLeftButtonDown += new MouseButtonEventHandler(OnMouseLeftButtonDown);
  51. dataGrid.MouseMove += new MouseEventHandler(OnMouseMove);
  52. }
  53. else
  54. {
  55. dataGrid.BeginningEdit -= new EventHandler<DataGridBeginningEditEventArgs>(OnBeginEdit);
  56. dataGrid.CellEditEnding -= new EventHandler<DataGridCellEditEndingEventArgs>(OnEndEdit);
  57. dataGrid.MouseLeftButtonUp -= new System.Windows.Input.MouseButtonEventHandler(OnMouseLeftButtonUp);
  58. dataGrid.MouseLeftButtonDown -= new MouseButtonEventHandler(OnMouseLeftButtonDown);
  59. dataGrid.MouseMove -= new MouseEventHandler(OnMouseMove);
  60.  
  61. dataGrid = null;
  62. popup = null;
  63. draggedItem = null;
  64. IsEditing = false;
  65. IsDragging = false;
  66. }
  67. }
  68.  
  69. public static bool GetEnabled(DependencyObject obj)
  70. {
  71. return (bool)obj.GetValue(EnabledProperty);
  72. }
  73.  
  74. public static void SetEnabled(DependencyObject obj, bool value)
  75. {
  76. obj.SetValue(EnabledProperty, value);
  77. }
  78.  
  79. // Using a DependencyProperty as the backing store for Enabled. This enables animation, styling, binding, etc...
  80. public static readonly DependencyProperty EnabledProperty =
  81. DependencyProperty.RegisterAttached("Enabled", typeof(bool), typeof(DragDropRowBehavior), new UIPropertyMetadata(false,OnEnabledChanged));
  82.  
  83. private static void OnEnabledChanged(DependencyObject depObject,DependencyPropertyChangedEventArgs e)
  84. {
  85. //Check if value is a Boolean Type
  86. if (e.NewValue is bool == false)
  87. throw new ArgumentException("Value should be of bool type", "Enabled");
  88.  
  89. enable = (bool)e.NewValue;
  90.  
  91. }
  92.  
  93. public static bool IsEditing { get; set; }
  94.  
  95. public static bool IsDragging { get; set; }
  96.  
  97. private static void OnBeginEdit(object sender, DataGridBeginningEditEventArgs e)
  98. {
  99. IsEditing = true;
  100. //in case we are in the middle of a drag/drop operation, cancel it...
  101. if (IsDragging) ResetDragDrop();
  102. }
  103.  
  104. private static void OnEndEdit(object sender, DataGridCellEditEndingEventArgs e)
  105. {
  106. IsEditing = false;
  107. }
  108.  
  109.  
  110. /// <summary>
  111. /// Initiates a drag action if the grid is not in edit mode.
  112. /// </summary>
  113. private static void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  114. {
  115. if (IsEditing) return;
  116.  
  117. var row = UIHelpers.TryFindFromPoint<DataGridRow>((UIElement)sender, e.GetPosition(dataGrid));
  118. if (row == null || row.IsEditing) return;
  119.  
  120. //set flag that indicates we're capturing mouse movements
  121. IsDragging = true;
  122. DraggedItem = row.Item;
  123. }
  124.  
  125. /// <summary>
  126. /// Completes a drag/drop operation.
  127. /// </summary>
  128. private static void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
  129. {
  130. if (!IsDragging || IsEditing)
  131. {
  132. return;
  133. }
  134.  
  135. //get the target item
  136. var targetItem = dataGrid.SelectedItem;
  137.  
  138. if (targetItem == null || !ReferenceEquals(DraggedItem, targetItem))
  139. {
  140. //remove the source from the list
  141. ((dataGrid).ItemsSource as IList).Remove(DraggedItem);
  142.  
  143. //get target index
  144. var targetIndex = ((dataGrid).ItemsSource as IList).IndexOf(targetItem);
  145.  
  146. //move source at the target's location
  147. ((dataGrid).ItemsSource as IList).Insert(targetIndex, DraggedItem);
  148.  
  149. //select the dropped item
  150. dataGrid.SelectedItem = DraggedItem;
  151. }
  152.  
  153. //reset
  154. ResetDragDrop();
  155. }
  156.  
  157. /// <summary>
  158. /// Closes the popup and resets the
  159. /// grid to read-enabled mode.
  160. /// </summary>
  161. private static void ResetDragDrop()
  162. {
  163. IsDragging = false;
  164. popup.IsOpen = false;
  165. dataGrid.IsReadOnly = false;
  166. }
  167.  
  168. /// <summary>
  169. /// Updates the popup's position in case of a drag/drop operation.
  170. /// </summary>
  171. private static void OnMouseMove(object sender, MouseEventArgs e)
  172. {
  173. if (!IsDragging || e.LeftButton != MouseButtonState.Pressed) return;
  174.  
  175. //display the popup if it hasn't been opened yet
  176. if (!popup.IsOpen)
  177. {
  178. //switch to read-only mode
  179. dataGrid.IsReadOnly = true;
  180.  
  181. //make sure the popup is visible
  182. popup.IsOpen = true;
  183. }
  184.  
  185.  
  186. Size popupSize = new Size(popup.ActualWidth, popup.ActualHeight);
  187. popup.PlacementRectangle = new Rect(e.GetPosition(dataGrid), popupSize);
  188.  
  189. //make sure the row under the grid is being selected
  190. Point position = e.GetPosition(dataGrid);
  191. var row = UIHelpers.TryFindFromPoint<DataGridRow>(dataGrid, position);
  192. if (row != null) dataGrid.SelectedItem = row.Item;
  193. }
  194.  
  195. }
  196.  
  197. #region find parent
  198.  
  199. /// <summary>
  200. /// Finds a parent of a given item on the visual tree.
  201. /// </summary>
  202. /// <typeparam name="T">The type of the queried item.</typeparam>
  203. /// <param name="child">A direct or indirect child of the
  204. /// queried item.</param>
  205. /// <returns>The first parent item that matches the submitted
  206. /// type parameter. If not matching item can be found, a null
  207. /// reference is being returned.</returns>
  208. public static T TryFindParent<T>(DependencyObject child)
  209. where T : DependencyObject
  210. {
  211. //get parent item
  212. DependencyObject parentObject = GetParentObject(child);
  213.  
  214. //we've reached the end of the tree
  215. if (parentObject == null) return null;
  216.  
  217. //check if the parent matches the type we're looking for
  218. T parent = parentObject as T;
  219. if (parent != null)
  220. {
  221. return parent;
  222. }
  223. else
  224. {
  225. //use recursion to proceed with next level
  226. return TryFindParent<T>(parentObject);
  227. }
  228. }
  229.  
  230.  
  231. /// <summary>
  232. /// This method is an alternative to WPF's
  233. /// <see cref="VisualTreeHelper.GetParent"/> method, which also
  234. /// supports content elements. Do note, that for content element,
  235. /// this method falls back to the logical tree of the element.
  236. /// </summary>
  237. /// <param name="child">The item to be processed.</param>
  238. /// <returns>The submitted item's parent, if available. Otherwise
  239. /// null.</returns>
  240. public static DependencyObject GetParentObject(DependencyObject child)
  241. {
  242. if (child == null) return null;
  243. ContentElement contentElement = child as ContentElement;
  244.  
  245. if (contentElement != null)
  246. {
  247. DependencyObject parent = ContentOperations.GetParent(contentElement);
  248. if (parent != null) return parent;
  249.  
  250. FrameworkContentElement fce = contentElement as FrameworkContentElement;
  251. return fce != null ? fce.Parent : null;
  252. }
  253.  
  254. //if it's not a ContentElement, rely on VisualTreeHelper
  255. return VisualTreeHelper.GetParent(child);
  256. }
  257.  
  258. #endregion
  259.  
  260.  
  261. #region update binding sources
  262.  
  263. /// <summary>
  264. /// Recursively processes a given dependency object and all its
  265. /// children, and updates sources of all objects that use a
  266. /// binding expression on a given property.
  267. /// </summary>
  268. /// <param name="obj">The dependency object that marks a starting
  269. /// point. This could be a dialog window or a panel control that
  270. /// hosts bound controls.</param>
  271. /// <param name="properties">The properties to be updated if
  272. /// <paramref name="obj"/> or one of its childs provide it along
  273. /// with a binding expression.</param>
  274. public static void UpdateBindingSources(DependencyObject obj,
  275. params DependencyProperty[] properties)
  276. {
  277. foreach (DependencyProperty depProperty in properties)
  278. {
  279. //check whether the submitted object provides a bound property
  280. //that matches the property parameters
  281. BindingExpression be = BindingOperations.GetBindingExpression(obj, depProperty);
  282. if (be != null) be.UpdateSource();
  283. }
  284.  
  285. int count = VisualTreeHelper.GetChildrenCount(obj);
  286. for (int i = 0; i < count; i++)
  287. {
  288. //process child items recursively
  289. DependencyObject childObject = VisualTreeHelper.GetChild(obj, i);
  290. UpdateBindingSources(childObject, properties);
  291. }
  292. }
  293.  
  294. #endregion
  295.  
  296.  
  297. /// <summary>
  298. /// Tries to locate a given item within the visual tree,
  299. /// starting with the dependency object at a given position.
  300. /// </summary>
  301. /// <typeparam name="T">The type of the element to be found
  302. /// on the visual tree of the element at the given location.</typeparam>
  303. /// <param name="reference">The main element which is used to perform
  304. /// hit testing.</param>
  305. /// <param name="point">The position to be evaluated on the origin.</param>
  306. public static T TryFindFromPoint<T>(UIElement reference, Point point)
  307. where T : DependencyObject
  308. {
  309. DependencyObject element = reference.InputHitTest(point)
  310. as DependencyObject;
  311. if (element == null) return null;
  312. else if (element is T) return (T)element;
  313. else return TryFindParent<T>(element);
  314. }
  315.  
  316. using System;
  317. using System.Collections.Generic;
  318. using System.Linq;
  319. using System.Text;
  320. using System.Windows;
  321. using System.Windows.Controls;
  322. using System.Windows.Controls.Primitives;
  323. using Microsoft.Windows.Controls;
  324. using System.Windows.Input;
  325. using System.Collections;
  326.  
  327. namespace DataGridDragAndDrop
  328. {
  329. public static class DragDropRowBehavior
  330. {
  331. private static DataGrid dataGrid;
  332.  
  333. private static Popup popup;
  334.  
  335. private static bool enable;
  336.  
  337. private static object draggedItem;
  338.  
  339. public static object DraggedItem
  340. {
  341. get { return DragDropRowBehavior.draggedItem; }
  342. set { DragDropRowBehavior.draggedItem = value; }
  343. }
  344.  
  345. public static Popup GetPopupControl(DependencyObject obj)
  346. {
  347. return (Popup)obj.GetValue(PopupControlProperty);
  348. }
  349.  
  350. public static void SetPopupControl(DependencyObject obj, Popup value)
  351. {
  352. obj.SetValue(PopupControlProperty, value);
  353. }
  354.  
  355. // Using a DependencyProperty as the backing store for PopupControl. This enables animation, styling, binding, etc...
  356. public static readonly DependencyProperty PopupControlProperty =
  357. DependencyProperty.RegisterAttached("PopupControl", typeof(Popup), typeof(DragDropRowBehavior), new UIPropertyMetadata(null, OnPopupControlChanged));
  358.  
  359. private static void OnPopupControlChanged(DependencyObject depObject, DependencyPropertyChangedEventArgs e)
  360. {
  361. if (e.NewValue == null || !(e.NewValue is Popup))
  362. {
  363. throw new ArgumentException("Popup Control should be set", "PopupControl");
  364. }
  365. popup = e.NewValue as Popup;
  366.  
  367. dataGrid = depObject as DataGrid;
  368. // Check if DataGrid
  369. if (dataGrid == null)
  370. return;
  371.  
  372.  
  373. if (enable && popup != null)
  374. {
  375. dataGrid.BeginningEdit += new EventHandler<DataGridBeginningEditEventArgs>(OnBeginEdit);
  376. dataGrid.CellEditEnding += new EventHandler<DataGridCellEditEndingEventArgs>(OnEndEdit);
  377. dataGrid.MouseLeftButtonUp += new System.Windows.Input.MouseButtonEventHandler(OnMouseLeftButtonUp);
  378. dataGrid.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(OnMouseLeftButtonDown);
  379. dataGrid.MouseMove += new MouseEventHandler(OnMouseMove);
  380. }
  381. else
  382. {
  383. dataGrid.BeginningEdit -= new EventHandler<DataGridBeginningEditEventArgs>(OnBeginEdit);
  384. dataGrid.CellEditEnding -= new EventHandler<DataGridCellEditEndingEventArgs>(OnEndEdit);
  385. dataGrid.MouseLeftButtonUp -= new System.Windows.Input.MouseButtonEventHandler(OnMouseLeftButtonUp);
  386. dataGrid.MouseLeftButtonDown -= new MouseButtonEventHandler(OnMouseLeftButtonDown);
  387. dataGrid.MouseMove -= new MouseEventHandler(OnMouseMove);
  388.  
  389. dataGrid = null;
  390. popup = null;
  391. draggedItem = null;
  392. IsEditing = false;
  393. IsDragging = false;
  394. }
  395. }
  396.  
  397. public static bool GetEnabled(DependencyObject obj)
  398. {
  399. return (bool)obj.GetValue(EnabledProperty);
  400. }
  401.  
  402. public static void SetEnabled(DependencyObject obj, bool value)
  403. {
  404. obj.SetValue(EnabledProperty, value);
  405. }
  406.  
  407. // Using a DependencyProperty as the backing store for Enabled. This enables animation, styling, binding, etc...
  408. public static readonly DependencyProperty EnabledProperty =
  409. DependencyProperty.RegisterAttached("Enabled", typeof(bool), typeof(DragDropRowBehavior), new UIPropertyMetadata(false,OnEnabledChanged));
  410.  
  411. private static void OnEnabledChanged(DependencyObject depObject,DependencyPropertyChangedEventArgs e)
  412. {
  413. //Check if value is a Boolean Type
  414. if (e.NewValue is bool == false)
  415. throw new ArgumentException("Value should be of bool type", "Enabled");
  416.  
  417. enable = (bool)e.NewValue;
  418.  
  419. }
  420.  
  421. public static bool IsEditing { get; set; }
  422.  
  423. public static bool IsDragging { get; set; }
  424.  
  425. private static void OnBeginEdit(object sender, DataGridBeginningEditEventArgs e)
  426. {
  427. IsEditing = true;
  428. //in case we are in the middle of a drag/drop operation, cancel it...
  429. if (IsDragging) ResetDragDrop();
  430. }
  431.  
  432. private static void OnEndEdit(object sender, DataGridCellEditEndingEventArgs e)
  433. {
  434. IsEditing = false;
  435. }
  436.  
  437.  
  438. /// <summary>
  439. /// Initiates a drag action if the grid is not in edit mode.
  440. /// </summary>
  441. private static void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  442. {
  443. if (IsEditing) return;
  444.  
  445. var row = UIHelpers.TryFindFromPoint<DataGridRow>((UIElement)sender, e.GetPosition(dataGrid));
  446. if (row == null || row.IsEditing) return;
  447.  
  448. //set flag that indicates we're capturing mouse movements
  449. IsDragging = true;
  450. DraggedItem = row.Item;
  451. }
  452.  
  453. /// <summary>
  454. /// Completes a drag/drop operation.
  455. /// </summary>
  456. private static void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
  457. {
  458. if (!IsDragging || IsEditing)
  459. {
  460. return;
  461. }
  462.  
  463. //get the target item
  464. var targetItem = dataGrid.SelectedItem;
  465.  
  466. if (targetItem == null || !ReferenceEquals(DraggedItem, targetItem))
  467. {
  468. //get target index
  469. var targetIndex = ((dataGrid).ItemsSource as IList).IndexOf(targetItem);
  470.  
  471. //remove the source from the list
  472. ((dataGrid).ItemsSource as IList).Remove(DraggedItem);
  473.  
  474. //move source at the target's location
  475. ((dataGrid).ItemsSource as IList).Insert(targetIndex, DraggedItem);
  476.  
  477. //select the dropped item
  478. dataGrid.SelectedItem = DraggedItem;
  479. }
  480.  
  481. //reset
  482. ResetDragDrop();
  483. }
  484.  
  485. /// <summary>
  486. /// Closes the popup and resets the
  487. /// grid to read-enabled mode.
  488. /// </summary>
  489. private static void ResetDragDrop()
  490. {
  491. IsDragging = false;
  492. popup.IsOpen = false;
  493. dataGrid.IsReadOnly = false;
  494. }
  495.  
  496. /// <summary>
  497. /// Updates the popup's position in case of a drag/drop operation.
  498. /// </summary>
  499. private static void OnMouseMove(object sender, MouseEventArgs e)
  500. {
  501. if (!IsDragging || e.LeftButton != MouseButtonState.Pressed) return;
  502.  
  503. popup.DataContext = DraggedItem;
  504. //display the popup if it hasn't been opened yet
  505. if (!popup.IsOpen)
  506. {
  507. //switch to read-only mode
  508. dataGrid.IsReadOnly = true;
  509.  
  510. //make sure the popup is visible
  511. popup.IsOpen = true;
  512. }
  513.  
  514.  
  515. Size popupSize = new Size(popup.ActualWidth, popup.ActualHeight);
  516. popup.PlacementRectangle = new Rect(e.GetPosition(dataGrid), popupSize);
  517.  
  518. //make sure the row under the grid is being selected
  519. Point position = e.GetPosition(dataGrid);
  520. var row = UIHelpers.TryFindFromPoint<DataGridRow>(dataGrid, position);
  521. if (row != null) dataGrid.SelectedItem = row.Item;
  522. }
  523.  
  524. }
  525. }
  526.  
  527. public static class UIHelpers
  528. {
  529.  
  530. #region find parent
  531.  
  532. /// <summary>
  533. /// Finds a parent of a given item on the visual tree.
  534. /// </summary>
  535. /// <typeparam name="T">The type of the queried item.</typeparam>
  536. /// <param name="child">A direct or indirect child of the
  537. /// queried item.</param>
  538. /// <returns>The first parent item that matches the submitted
  539. /// type parameter. If not matching item can be found, a null
  540. /// reference is being returned.</returns>
  541. public static T TryFindParent<T>(DependencyObject child)
  542. where T : DependencyObject
  543. {
  544. //get parent item
  545. DependencyObject parentObject = GetParentObject(child);
  546.  
  547. //we've reached the end of the tree
  548. if (parentObject == null) return null;
  549.  
  550. //check if the parent matches the type we're looking for
  551. T parent = parentObject as T;
  552. if (parent != null)
  553. {
  554. return parent;
  555. }
  556. else
  557. {
  558. //use recursion to proceed with next level
  559. return TryFindParent<T>(parentObject);
  560. }
  561. }
  562.  
  563.  
  564. /// <summary>
  565. /// This method is an alternative to WPF's
  566. /// <see cref="VisualTreeHelper.GetParent"/> method, which also
  567. /// supports content elements. Do note, that for content element,
  568. /// this method falls back to the logical tree of the element.
  569. /// </summary>
  570. /// <param name="child">The item to be processed.</param>
  571. /// <returns>The submitted item's parent, if available. Otherwise
  572. /// null.</returns>
  573. public static DependencyObject GetParentObject(DependencyObject child)
  574. {
  575. if (child == null) return null;
  576. ContentElement contentElement = child as ContentElement;
  577.  
  578. if (contentElement != null)
  579. {
  580. DependencyObject parent = ContentOperations.GetParent(contentElement);
  581. if (parent != null) return parent;
  582.  
  583. FrameworkContentElement fce = contentElement as FrameworkContentElement;
  584. return fce != null ? fce.Parent : null;
  585. }
  586.  
  587. //if it's not a ContentElement, rely on VisualTreeHelper
  588. return VisualTreeHelper.GetParent(child);
  589. }
  590.  
  591. #endregion
  592.  
  593.  
  594. #region update binding sources
  595.  
  596. /// <summary>
  597. /// Recursively processes a given dependency object and all its
  598. /// children, and updates sources of all objects that use a
  599. /// binding expression on a given property.
  600. /// </summary>
  601. /// <param name="obj">The dependency object that marks a starting
  602. /// point. This could be a dialog window or a panel control that
  603. /// hosts bound controls.</param>
  604. /// <param name="properties">The properties to be updated if
  605. /// <paramref name="obj"/> or one of its childs provide it along
  606. /// with a binding expression.</param>
  607. public static void UpdateBindingSources(DependencyObject obj,
  608. params DependencyProperty[] properties)
  609. {
  610. foreach (DependencyProperty depProperty in properties)
  611. {
  612. //check whether the submitted object provides a bound property
  613. //that matches the property parameters
  614. BindingExpression be = BindingOperations.GetBindingExpression(obj, depProperty);
  615. if (be != null) be.UpdateSource();
  616. }
  617.  
  618. int count = VisualTreeHelper.GetChildrenCount(obj);
  619. for (int i = 0; i < count; i++)
  620. {
  621. //process child items recursively
  622. DependencyObject childObject = VisualTreeHelper.GetChild(obj, i);
  623. UpdateBindingSources(childObject, properties);
  624. }
  625. }
  626.  
  627. #endregion
  628.  
  629.  
  630. /// <summary>
  631. /// Tries to locate a given item within the visual tree,
  632. /// starting with the dependency object at a given position.
  633. /// </summary>
  634. /// <typeparam name="T">The type of the element to be found
  635. /// on the visual tree of the element at the given location.</typeparam>
  636. /// <param name="reference">The main element which is used to perform
  637. /// hit testing.</param>
  638. /// <param name="point">The position to be evaluated on the origin.</param>
  639. public static T TryFindFromPoint<T>(UIElement reference, Point point)
  640. where T : DependencyObject
  641. {
  642. DependencyObject element = reference.InputHitTest(point)
  643. as DependencyObject;
  644. if (element == null) return null;
  645. else if (element is T) return (T)element;
  646. else return TryFindParent<T>(element);
  647. }
  648. }
  649.  
  650. <!-- Drag and Drop Popup -->
  651. <Popup x:Name="popup1"
  652. AllowsTransparency="True"
  653. IsHitTestVisible="False"
  654. Placement="RelativePoint"
  655. PlacementTarget="{Binding ElementName=shareGrid}">
  656.  
  657. <!-- Your own Popup construction Use properties of DraggedObject inside for Binding -->
  658.  
  659. <TextBlock Margin="8,0,0,0"
  660. VerticalAlignment="Center"
  661. FontSize="14"
  662. FontWeight="Bold"
  663.  
  664. <!-- I used name property of in my Dragged row -->
  665.  
  666. Text="{Binding Path=Name}" />
  667. </Popup>
  668. <DataGrid x:Name="myDataGrid"
  669. AutoGenerateColumns="False"
  670. CanUserAddRows="False"
  671. CanUserDeleteRows="False"
  672. CanUserReorderColumns="False"
  673. CanUserSortColumns="False"
  674. ItemsSource="{Binding}"
  675. SelectionMode="Single"
  676. this:DragDropRowBehavior.Enabled="True"
  677. this:DragDropRowBehavior.PopupControl="{Binding ElementName=popup1}"></DataGrid >
  678.  
  679. public class DragDropRowBehavior : Behavior<DataGrid>
  680. {
  681. private object draggedItem;
  682. private bool isEditing;
  683. private bool isDragging;
  684.  
  685. #region DragEnded
  686. public static readonly RoutedEvent DragEndedEvent =
  687. EventManager.RegisterRoutedEvent("DragEnded", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(DragDropRowBehavior));
  688. public static void AddDragEndedHandler(DependencyObject d, RoutedEventHandler handler)
  689. {
  690. UIElement uie = d as UIElement;
  691. if (uie != null)
  692. uie.AddHandler(DragDropRowBehavior.DragEndedEvent, handler);
  693. }
  694. public static void RemoveDragEndedHandler(DependencyObject d, RoutedEventHandler handler)
  695. {
  696. UIElement uie = d as UIElement;
  697. if (uie != null)
  698. uie.RemoveHandler(DragDropRowBehavior.DragEndedEvent, handler);
  699. }
  700.  
  701. private void RaiseDragEndedEvent()
  702. {
  703. var args = new RoutedEventArgs(DragDropRowBehavior.DragEndedEvent);
  704. AssociatedObject.RaiseEvent(args);
  705. }
  706. #endregion
  707.  
  708. #region Popup
  709. public static readonly DependencyProperty PopupProperty =
  710. DependencyProperty.Register("Popup", typeof(System.Windows.Controls.Primitives.Popup), typeof(DragDropRowBehavior));
  711. public System.Windows.Controls.Primitives.Popup Popup
  712. {
  713. get { return (System.Windows.Controls.Primitives.Popup)GetValue(PopupProperty); }
  714. set { SetValue(PopupProperty, value); }
  715. }
  716. #endregion
  717.  
  718. protected override void OnAttached()
  719. {
  720. base.OnAttached();
  721.  
  722. AssociatedObject.BeginningEdit += OnBeginEdit;
  723. AssociatedObject.CellEditEnding += OnEndEdit;
  724. AssociatedObject.MouseLeftButtonUp += OnMouseLeftButtonUp;
  725. AssociatedObject.PreviewMouseLeftButtonDown += OnMouseLeftButtonDown;
  726. AssociatedObject.MouseMove += OnMouseMove;
  727. }
  728.  
  729. protected override void OnDetaching()
  730. {
  731. base.OnDetaching();
  732.  
  733. AssociatedObject.BeginningEdit -= OnBeginEdit;
  734. AssociatedObject.CellEditEnding -= OnEndEdit;
  735. AssociatedObject.MouseLeftButtonUp -= OnMouseLeftButtonUp;
  736. AssociatedObject.MouseLeftButtonDown -= OnMouseLeftButtonDown;
  737. AssociatedObject.MouseMove -= OnMouseMove;
  738.  
  739. Popup = null;
  740. draggedItem = null;
  741. isEditing = false;
  742. isDragging = false;
  743. }
  744.  
  745. private void OnBeginEdit(object sender, DataGridBeginningEditEventArgs e)
  746. {
  747. isEditing = true;
  748. //in case we are in the middle of a drag/drop operation, cancel it...
  749. if (isDragging) ResetDragDrop();
  750. }
  751.  
  752. private void OnEndEdit(object sender, DataGridCellEditEndingEventArgs e)
  753. {
  754. isEditing = false;
  755. }
  756.  
  757. private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  758. {
  759. if (isEditing) return;
  760.  
  761. var row = UIHelpers.TryFindFromPoint<DataGridRow>((UIElement)sender, e.GetPosition(AssociatedObject));
  762. if (row == null || row.IsEditing) return;
  763.  
  764. //set flag that indicates we're capturing mouse movements
  765. isDragging = true;
  766. draggedItem = row.Item;
  767. }
  768.  
  769. private void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
  770. {
  771. if (!isDragging || isEditing)
  772. return;
  773.  
  774. //get the target item
  775. var targetItem = AssociatedObject.SelectedItem;
  776.  
  777. if (targetItem == null || !ReferenceEquals(draggedItem, targetItem))
  778. {
  779. //get target index
  780. var targetIndex = ((AssociatedObject).ItemsSource as IList).IndexOf(targetItem);
  781.  
  782. //remove the source from the list
  783. ((AssociatedObject).ItemsSource as IList).Remove(draggedItem);
  784.  
  785. //move source at the target's location
  786. ((AssociatedObject).ItemsSource as IList).Insert(targetIndex, draggedItem);
  787.  
  788. //select the dropped item
  789. AssociatedObject.SelectedItem = draggedItem;
  790. RaiseDragEndedEvent();
  791. }
  792.  
  793. //reset
  794. ResetDragDrop();
  795. }
  796.  
  797. private void ResetDragDrop()
  798. {
  799. isDragging = false;
  800. Popup.IsOpen = false;
  801. AssociatedObject.IsReadOnly = false;
  802. }
  803.  
  804. private void OnMouseMove(object sender, MouseEventArgs e)
  805. {
  806. if (!isDragging || e.LeftButton != MouseButtonState.Pressed)
  807. return;
  808.  
  809. Popup.DataContext = draggedItem;
  810. //display the popup if it hasn't been opened yet
  811. if (!Popup.IsOpen)
  812. {
  813. //switch to read-only mode
  814. AssociatedObject.IsReadOnly = true;
  815.  
  816. //make sure the popup is visible
  817. Popup.IsOpen = true;
  818. }
  819.  
  820. var popupSize = new Size(Popup.ActualWidth, Popup.ActualHeight);
  821. Popup.PlacementRectangle = new Rect(e.GetPosition(AssociatedObject), popupSize);
  822.  
  823. //make sure the row under the grid is being selected
  824. var position = e.GetPosition(AssociatedObject);
  825. var row = UIHelpers.TryFindFromPoint<DataGridRow>(AssociatedObject, position);
  826. if (row != null) AssociatedObject.SelectedItem = row.Item;
  827. }
  828. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement