public static UIElement GetClosestItemContainerToPosition(ItemsControl itemsControl, Point point, Orientation orientation) { Type itemContainerType = ControlMethods.GetItemContainerType(itemsControl); if (itemContainerType == null) { return(null); } List <UIElement> containers = new List <UIElement>(); LineGeometry line; switch (orientation) { case Orientation.Horizontal: line = new LineGeometry(new Point(0d, point.Y), new Point(itemsControl.RenderSize.Width, point.Y)); break; default: line = new LineGeometry(new Point(point.X, 0d), new Point(point.X, itemsControl.RenderSize.Height)); break; } line.Freeze(); VisualTreeHelper.HitTest( itemsControl, null, testResult => { UIElement itemContainer = testResult.VisualHit.FindVisualTreeAncestor(itemContainerType) as UIElement; if (itemContainer != null && itemsControl.Equals(ItemsControl.ItemsControlFromItemContainer(itemContainer))) { containers.Add(itemContainer); } return(HitTestResultBehavior.Continue); }, new GeometryHitTestParameters(line) ); switch (containers.Count) { case 0: return(null); case 1: return(containers[0]); } // Find closest item to the point clicked. UIElement closest = null; double closestDistance = double.MaxValue; foreach (UIElement container in containers) { Point transform = container.TransformToAncestor(itemsControl).Transform(default(Point)); double distance = Math.Abs(orientation == Orientation.Horizontal ? point.X - transform.X : point.Y - transform.Y); if (distance < closestDistance) { closest = container; closestDistance = distance; } } return(closest); }
public static UIElement GetItemContainer(this ItemsControl itemsControl, UIElement child) { Type itemContainerType = ControlMethods.GetItemContainerType(itemsControl); if (itemContainerType == null) { return(null); } for (UIElement element = VisualTreeHelper.GetParent(child) as UIElement; element != null && !itemsControl.Equals(element); element = VisualTreeHelper.GetParent(element) as UIElement) { if (itemContainerType.IsInstanceOfType(element) && itemsControl.Equals(ItemsControl.ItemsControlFromItemContainer(element))) { return(element); } } return(null); }
private static void TabControl_PreviewMouseMove(object sender, MouseEventArgs e) { TabControl tabControl = (TabControl)sender; Point point = e.GetPosition(tabControl); if (tabControl.IsMouseCaptured) { TabTearOffBehavior.UpdateDragWindowLocation(tabControl); Window dropWindow = TabTearOffBehavior.GetWindowMouseIsOver(e); if (dropWindow == null) { return; } if (!dropWindow.IsActive) { dropWindow.Activate(); } ITabTearOffHandler targetHandler; TabControl targetTabControl = TabTearOffBehavior.FindTargetTabControl(dropWindow, out targetHandler); Panel panel = ControlMethods.GetPanel(targetTabControl); if (TabTearOffBehavior.IsMouseInDropLocation(e, targetTabControl, panel)) { if (TabTearOffBehavior._adorner == null || !TabTearOffBehavior._adorner.AdornedElement.Equals(targetTabControl)) { if (TabTearOffBehavior._adorner != null) { TabTearOffBehavior._adorner.Detach(); } TabTearOffBehavior._adorner = new InsertionAdorner(targetTabControl, panel.GetOrientation()); } TabTearOffBehavior._adorner.UpdateLocation(e); } else if (TabTearOffBehavior._adorner != null) { TabTearOffBehavior._adorner.Detach(); TabTearOffBehavior._adorner = null; } } else if (TabTearOffBehavior.IsSufficientDragMove(point)) { Rectangle contentRectangle = TabTearOffBehavior.CreateRectangle((Visual)TabTearOffBehavior.GetContent(tabControl)); Rectangle tabItemRectangle = TabTearOffBehavior.CreateRectangle(TabTearOffBehavior._activeTabItem); Panel.SetZIndex(tabItemRectangle, 10); StackPanel stackPanel = new StackPanel { Orientation = tabControl.TabStripPlacement == Dock.Right || tabControl.TabStripPlacement == Dock.Left ? Orientation.Horizontal : Orientation.Vertical, Children = { tabItemRectangle } }; stackPanel.Children.Insert(tabControl.TabStripPlacement == Dock.Right || tabControl.TabStripPlacement == Dock.Bottom ? 0 : 1, contentRectangle); TranslateTransform translateTransform = new TranslateTransform(); switch (tabControl.TabStripPlacement) { case Dock.Bottom: translateTransform.Y = -1d; break; case Dock.Left: translateTransform.X = 1d; break; case Dock.Right: translateTransform.X = -1d; break; case Dock.Top: translateTransform.Y = 1d; break; } tabItemRectangle.RenderTransform = translateTransform; TabTearOffBehavior._dragWindow = new Window { Topmost = true, AllowsTransparency = true, WindowStyle = WindowStyle.None, IsHitTestVisible = false, SizeToContent = SizeToContent.WidthAndHeight, Background = Brushes.Transparent, Content = new Border { Child = stackPanel, Opacity = 0.75 } }; TabTearOffBehavior.UpdateDragWindowLocation(tabControl); TabTearOffBehavior._dragWindow.Show(); tabControl.MouseLeave -= TabTearOffBehavior.TabControl_MouseLeaveOrLostCapture; tabControl.CaptureMouse(); e.Handled = true; } }
internal static int DetermineInsertionIndex(ItemsControl tabControl, MouseEventArgs mouseEventArgs, Orientation panelOrientation) { Point tabControlPosition = mouseEventArgs.GetPosition(tabControl); UIElement container = tabControl.GetItemContainerAtPosition(tabControlPosition) ?? ControlMethods.GetClosestItemContainerToPosition(tabControl, tabControlPosition, panelOrientation); if (container == null) { return(0); } int index = tabControl.ItemContainerGenerator.IndexFromContainer(container); Point containerPosition = mouseEventArgs.GetPosition(container); if (panelOrientation == Orientation.Vertical && containerPosition.Y > container.RenderSize.Height / 2d || panelOrientation == Orientation.Horizontal && containerPosition.X > container.RenderSize.Width / 2d) { index++; } return(index); }
private static void TabControl_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e) { TabControl sourceTabControl = (TabControl)sender; sourceTabControl.PreviewMouseLeftButtonUp -= TabTearOffBehavior.TabControl_PreviewMouseLeftButtonUp; sourceTabControl.PreviewMouseMove -= TabTearOffBehavior.TabControl_PreviewMouseMove; sourceTabControl.MouseLeave -= TabTearOffBehavior.TabControl_MouseLeaveOrLostCapture; sourceTabControl.LostMouseCapture -= TabTearOffBehavior.TabControl_MouseLeaveOrLostCapture; if (sourceTabControl.IsMouseCaptured) { TabItem tabItem = TabTearOffBehavior._activeTabItem; Point dragWindowLocation = new Point { X = TabTearOffBehavior._dragWindow.Left, Y = TabTearOffBehavior._dragWindow.Top }; sourceTabControl.ReleaseMouseCapture(); if (TabTearOffBehavior._adorner != null) { TabTearOffBehavior._adorner.Detach(); TabTearOffBehavior._adorner = null; } TabTearOffBehavior._dragWindow.Close(); TabTearOffBehavior._dragWindow = null; TabTearOffBehavior._activeTabItem = null; object item = sourceTabControl.ItemContainerGenerator.ItemFromContainer(tabItem); int sourceIndex = sourceTabControl.ItemContainerGenerator.IndexFromContainer(tabItem); Window dropWindow = TabTearOffBehavior.GetWindowMouseIsOver(e); TabControl targetTabControl; Panel targetPanel; ITabTearOffHandler targetHandler; if (dropWindow != null && TabTearOffBehavior.IsMouseInDropLocation(e, targetTabControl = TabTearOffBehavior.FindTargetTabControl(dropWindow, out targetHandler), targetPanel = ControlMethods.GetPanel(targetTabControl))) { int insertionIndex = TabTearOffBehavior.DetermineInsertionIndex(targetTabControl, e, targetPanel.GetOrientation()); if (!object.ReferenceEquals(sourceTabControl, targetTabControl)) { if (targetHandler.AllowTargetedDrop(item, sourceTabControl, sourceIndex, targetTabControl, insertionIndex)) { targetHandler.HandleTargetedDrop(item, sourceTabControl, sourceIndex, targetTabControl, insertionIndex); } } else if (sourceTabControl.Items.Count != 1 && insertionIndex != sourceIndex && targetHandler.AllowReorder(item, sourceTabControl, sourceIndex, insertionIndex)) { targetHandler.HandleReorder(item, sourceTabControl, sourceIndex, insertionIndex); } } else { ITabTearOffHandler sourceHandler = TabTearOffBehavior.GetHandler(sourceTabControl); if (sourceHandler.AllowTargetlessDrop(item, sourceTabControl, sourceIndex, dragWindowLocation)) { sourceHandler.HandleTargetlessDrop(item, sourceTabControl, sourceIndex, dragWindowLocation); } } } e.Handled = true; }