青岛做门户网站公司,网站常用特效,临海受欢迎营销型网站建设,如何自己制作一个网站拖放官方文档
拖放操作通常涉及两个参与方#xff1a;拖动对象所源自的拖动源和接收放置对象的拖放目标。 拖动源和放置目标可能是相同应用程序或不同应用程序中的 UI 元素。
我这里实现的是对TabControl的Tab页面进行拖放#xff0c;以达成类似Chrome浏览器的拖放功能。
…拖放官方文档
拖放操作通常涉及两个参与方拖动对象所源自的拖动源和接收放置对象的拖放目标。 拖动源和放置目标可能是相同应用程序或不同应用程序中的 UI 元素。
我这里实现的是对TabControl的Tab页面进行拖放以达成类似Chrome浏览器的拖放功能。
对拖放相关事件研究后发现最终只需要在拖动源事件处理程序中调用 DoDragDrop 方法启动拖动操作然后在拖放目标上响应Drop事件。启动拖放操作的拖动源事件通常是 MouseMove事件另外需要判断鼠标左键是否为按下状态。另外最好判断一下鼠标移动的距离是否大于最小拖动距离在我没有添加这个检查之前双击也会触发拖动事件。
除了正常拖动将Tab页从一个TabControl 拖动到另一个 TabControl 中考虑将Tab页拖动到窗口之外的情况浏览器在这种情况下会创建一个新的窗口来显示这个Tab页我这里采用类似的方式创建一个预设的子窗口来显示该Tab页面。
此外当Tab页面在原TabControl内部拖动时根据拖动位置调整Tab页面的顺序。
我这里对原生的TabControl进行了继承封装了几个响应事件轻量化的实现了拖放效果。
TabControlDragable.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;namespace WpfLibrary;public class TabControlDragable : TabControl
{public TabControlDragable(){AddHandler(MouseLeftButtonDownEvent, new MouseButtonEventHandler(OnMouseLeftButtonDown), true);AddHandler(MouseLeftButtonUpEvent, new MouseButtonEventHandler(OnMouseLeftButtonUp), true);AddHandler(MouseMoveEvent, new MouseEventHandler(OnMouseMove), true);AddHandler(DropEvent, new DragEventHandler(OnDrop), true);MinWidth 100;MinHeight 100;AllowDrop true;}private bool IsDraging false;private object? DragData;private Point DragStartPosition;private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e){Point p e.GetPosition(this);DragData DragUtility.GetDataObjectFromItemsControl(this, p);if (DragData ! null){DragStartPosition p;}e.Handled true;}private void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e){ResetState();e.Handled true;}private void OnMouseMove(object sender, MouseEventArgs e){if (DragData null || DragData is not TabItem){return;}Point currentPosition e.GetPosition(this);if (e.LeftButton MouseButtonState.Pressed !IsDraging ((Math.Abs(currentPosition.X - DragStartPosition.X) SystemParameters.MinimumHorizontalDragDistance) || (Math.Abs(currentPosition.Y - DragStartPosition.Y) SystemParameters.MinimumVerticalDragDistance))){DataObject dataObject new DataObject();dataObject.SetData(DragData, DragData);var effects DragDrop.DoDragDrop(this, dataObject, DragDropEffects.Move);if (effects DragDropEffects.None){if (Items.Count ! 1){var tabItem DragData as TabItem;var parentWindow DragUtility.GetParentWindow(tabItem);Items.Remove(tabItem);ChildWindow newChildWindow new ChildWindow();if (parentWindow is ChildWindow){newChildWindow.Owner parentWindow.Owner;}else{newChildWindow.Owner parentWindow;}newChildWindow.DataContext parentWindow?.DataContext;var tabControl new TabControlDragable();newChildWindow.MyGrid.Children.Add(tabControl);tabControl.Items.Add(tabItem);newChildWindow.Show();}}ResetState();}e.Handled true;}private int MeasureIndex(TabControl targetTabControl, Point point){double preWidth 0.0;for (var i 0; i targetTabControl.Items.Count; i){var item targetTabControl.Items[i] as TabItem;if (item null){continue;}if (point.Y item.ActualHeight){return targetTabControl.Items.Count;}if (point.X preWidth item.ActualWidth / 2){return i;}else{preWidth item.ActualWidth;}}return targetTabControl.Items.Count;}private void OnDrop(object sender, DragEventArgs e){var tabItem e.Data.GetData(DragData) as TabItem;var parentTabControl tabItem?.Parent as TabControl;if (tabItem null || parentTabControl null){return;}var point e.GetPosition(this);int index MeasureIndex(this, point);if (this ! parentTabControl){var parentWindow DragUtility.GetParentWindow(parentTabControl);if (parentTabControl.Items.Count 1){var childWindow parentWindow as ChildWindow;if (childWindow ! null){parentTabControl.Items.Remove(tabItem);this.Items.Insert(index, tabItem);this.SelectedItem tabItem;childWindow?.Close();}}else{parentTabControl.Items.Remove(tabItem);this.Items.Insert(index, tabItem);this.SelectedItem tabItem;}}else if (index parentTabControl.Items.IndexOf(tabItem)){parentTabControl.Items.Remove(tabItem);parentTabControl.Items.Insert(index, tabItem);parentTabControl.SelectedItem tabItem;}else if (index parentTabControl.Items.IndexOf(tabItem)){parentTabControl.Items.Remove(tabItem);parentTabControl.Items.Insert(index - 1, tabItem);parentTabControl.SelectedItem tabItem;}e.Handled true;}private void ResetState(){IsDraging false;DragData null;}
}使用起来也很简单只需要将TabControl 替换为 TabControlDragable 即可事件已经绑定好了。
MainWindow.xaml
Window x:ClassWpfLibraryTest.MainWindowxmlnshttp://schemas.microsoft.com/winfx/2006/xaml/presentationxmlns:xhttp://schemas.microsoft.com/winfx/2006/xamlxmlns:dhttp://schemas.microsoft.com/expression/blend/2008xmlns:mchttp://schemas.openxmlformats.org/markup-compatibility/2006xmlns:localclr-namespace:WpfLibraryTestxmlns:wpfLibraryclr-namespace:WpfLibrary;assemblyWpfLibrarymc:IgnorabledTitleMainWindow Height450 Width800GridGrid.RowDefinitionsRowDefinition Height*/RowDefinition Height*//Grid.RowDefinitionswpfLibrary:TabControlDragable Grid.Row0 x:NametabControl1TabItem HeadertabControl1Item1DataGrid ItemsSource{Binding PathAccounts} IsReadOnlyTrue/DataGrid/TabItemTabItem HeadertabControl1Item2DataGrid ItemsSource{Binding PathAccounts2} IsReadOnlyTrue/DataGrid/TabItemTabItem HeadertabControl1Item3DataGrid ItemsSource{Binding PathAccounts3} IsReadOnlyTrue/DataGrid/TabItem/wpfLibrary:TabControlDragablewpfLibrary:TabControlDragable Grid.Row1 x:NametabControl2TabItem HeadertabControl2Item1DataGrid ItemsSource{Binding PathAccounts} IsReadOnlyTrue/DataGrid/TabItemTabItem HeadertabControl2Item2DataGrid ItemsSource{Binding PathAccounts2} IsReadOnlyTrue/DataGrid/TabItemTabItem HeadertabControl2Item3DataGrid ItemsSource{Binding PathAccounts3} IsReadOnlyTrue/DataGrid/TabItem/wpfLibrary:TabControlDragable/Grid
/Window