public static void SetIndexChangeable(this Control control, StackPanel parentStackPanel, IndexChangedDelegate OnIndexChanged = null) { Control grabbedItem = null; int grabbedIndex = 0; bool onDragging = false; control.MouseDown += (object sender, MouseButtonEventArgs e) => { if (e.ChangedButton == MouseButton.Left) { onDragging = true; Mouse.Capture(control); grabbedItem = control; grabbedIndex = parentStackPanel.Children.IndexOf(control); } }; control.MouseMove += (object sender, MouseEventArgs e) => { if (!onDragging) { return; } //Find Cursor Index int newIndex = -1; Control item; int count = parentStackPanel.Children.Count; for (int i = 0; i < count; ++i) { item = (Control)parentStackPanel.Children[i]; float itemHalfHeight = (float)(item.ActualHeight * 0.5f); if (MouseInput.AbsolutePosition.y < item.GetAbsolutePosition(new Vector2(0, itemHalfHeight)).y) { newIndex = i; break; } } if (newIndex == -1) { newIndex = count; } if (newIndex != grabbedIndex) { if (newIndex > grabbedIndex) { --newIndex; } parentStackPanel.Children.Remove(grabbedItem); parentStackPanel.Children.Insert(newIndex, grabbedItem); OnIndexChanged?.Invoke(grabbedIndex, newIndex); grabbedIndex = newIndex; } }; control.MouseUp += (object sender, MouseButtonEventArgs e) => { if (e.ChangedButton == MouseButton.Left) { onDragging = false; Mouse.Capture(null); } }; }
public static void SetIndexChangeableContext <ElementType>(this StackPanel context, IndexChangedDelegate OnIndexChanged = null) where ElementType : FrameworkElement { ElementType grabbedItem = null; int grabbedIndex = 0; bool onDragging = false; context.MouseDown += (object sender, MouseButtonEventArgs e) => { if (e.ChangedButton != MouseButton.Left) { return; } if (e.OriginalSource is FrameworkElement) { grabbedItem = GetPressedItem((FrameworkElement)e.OriginalSource); } if (grabbedItem == null) { return; } int initGrabbedIndex = context.Children.IndexOf(grabbedItem); grabbedIndex = initGrabbedIndex; Mouse.Capture(grabbedItem); onDragging = true; }; context.MouseMove += (object sender, MouseEventArgs e) => { if (!onDragging) { return; } //Find Cursor Index int newIndex = -1; FrameworkElement item; int count = context.Children.Count; for (int i = 0; i < count; ++i) { item = (FrameworkElement)context.Children[i]; float itemHalfHeight = (float)(item.ActualHeight * 0.5f); if (MouseInput.AbsolutePosition.y < item.GetAbsolutePosition(new Vector2(0, itemHalfHeight)).y) { newIndex = i; break; } } if (newIndex == -1) { newIndex = count; } if (newIndex != grabbedIndex) { if (newIndex > grabbedIndex) { --newIndex; } context.Children.Remove(grabbedItem); context.Children.Insert(newIndex, grabbedItem); OnIndexChanged?.Invoke(grabbedIndex, newIndex); grabbedIndex = newIndex; } }; context.MouseUp += (object sender, MouseButtonEventArgs e) => { if (e.ChangedButton != MouseButton.Left) { return; } onDragging = false; Mouse.Capture(null); }; ElementType GetPressedItem(FrameworkElement pressedElement) { //부모 트리로 Item이 나올 때까지 탐색하는 함수이다. DependencyObject parent = pressedElement.Parent; if (pressedElement is ElementType && parent == context) { return(pressedElement as ElementType); } else if (parent != null && !(parent is Window) && parent is FrameworkElement) { return(GetPressedItem((FrameworkElement)parent)); } else { return(null); } } }