WPF MultiSelect模式下ListBox 实现多个ListBoxItem拖拽
WPF 的ListBox不支持很多常见的用户习惯,如在Explorer中用鼠标可以选择多项Item,并且点击已经选择的Item,按住鼠标左键可以将所有已选择Item拖拽到指定的位置。本文简单的实现了这一功能。
效果图:
拖拽1个Item
拖拽多个Item
说明:
代码下载地址:http://download.csdn.net/download/u012566751/6452323
代码中使用了两个类:
1.DragDropAdorner,用于拖拽过程中显示预览图,代码来自CSDN
2.ListBoxSelectionHelper,用于通过鼠标拖拽框选ListBoxItem,代码来自Codeproject,作者略作修改
具体操作
1.创建一个WPF工程,WpfDragMultiSelect,主界面代码如下:
<Grid><Grid.RowDefinitions><RowDefinition Height="5"/><RowDefinition Height="*"/><RowDefinition Height="5"/></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition Width="5"/><ColumnDefinition Width="50"/><ColumnDefinition Width="5"/><ColumnDefinition Width="*"/><ColumnDefinition Width="5"/></Grid.ColumnDefinitions><Grid Grid.Row="1" Grid.Column="1" Background="Black"/><GridSplitter Grid.Row="1" Grid.Column="2"ShowsPreview="True"HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/><Grid Grid.Row="1" Grid.Column="3" Background="Gray"></Grid></Grid>
2.创建一个列表,使用数据绑定方式,数据类如下:
class ListData{public int Number{get;set;}public ListData(int nNum){Number = nNum;}}
数据类只有一个公共属性Number,类型为int
主类添加代码:
List<ListData> _list = new List<ListData>(); AdornerLayer mAdornerLayer = null; bool bIsDraging = false;public MainWindow(){InitializeComponent();for (int n = 0; n < 600; n++ ){this._list.Add(new ListData(n));}this.DataContext = _list;this.list.AllowDrop = true;this.list.QueryContinueDrag += delegate(object sender, QueryContinueDragEventArgs e){//_adornerLayer.Update();//this.list.Cursor = Cursors.Arrow; mAdornerLayer.Update();};}
_list作为列表数据源
bIsDraging表示数据拖拽状态
列表数据模板如下:
<DataTemplate x:Key="dt_Rectangle"><Grid Margin="10" ><Rectangle Width="50"Height="50" Fill="LightBlue" RadiusX="3" RadiusY="3" /><TextBlock Text="{Binding Path=Number}"Foreground="White"VerticalAlignment="Center"HorizontalAlignment="Center"/><Rectangle Width="50"Height="50"Fill="Transparent"PreviewMouseDown="Rectangle_PreviewMouseDown" PreviewMouseMove="Rectangle_PreviewMouseMove" PreviewMouseUp="Rectangle_PreviewMouseUp" /></Grid></DataTemplate>
每个列表显示为一个亮蓝色(LightBlue)的正方形,在每个正方形中显示该项绑定ListData对象的Number属性。
最后一个Rectangle专门用于响应鼠标事件
在主界面中添加列表:
<ListBox x:Name="list" Background="Transparent"ItemsSource="{Binding}"ScrollViewer.HorizontalScrollBarVisibility="Disabled"loc:ListBoxSelectionHelper.MultiSelect="True" loc:ListBoxSelectionHelper.PreviewDrag="True" PreviewDragEnter="list_PreviewDragEnter"><ListBox.ItemTemplate><DynamicResource ResourceKey="dt_Rectangle"/></ListBox.ItemTemplate><ListBox.ItemsPanel><ItemsPanelTemplate><WrapPanel/></ItemsPanelTemplate></ListBox.ItemsPanel></ListBox>
代码:loc:ListBoxSelectionHelper.MultiSelect="True" loc:ListBoxSelectionHelper.PreviewDrag="True" ,使用ListBoxSelectionHelper类实现鼠标拖拽框选功能
3.添加一个Grid,用于在拖拽过程中显示预览
<!--拖拽预览--><Grid Width="100"Height="100"><Grid x:Name="gridAdorner" Visibility="Hidden"><Rectangle Width="50"Height="50"Fill="LightGray"/><TextBlock x:Name="textAdorner" Text="0"VerticalAlignment="Center"HorizontalAlignment="Center" Foreground="Red" FontSize="20"></TextBlock></Grid></Grid>
4.实现数据模板dt_Rectangle中声明的事件,用以支持拖拽功能
private void Rectangle_PreviewMouseDown(object sender, MouseButtonEventArgs e){var rectangle = (FrameworkElement)sender;var rectangleViewModel = (ListData)rectangle.DataContext;ListBoxItem lstitem = this.list.ItemContainerGenerator.ContainerFromItem(rectangleViewModel) as ListBoxItem;if (lstitem.IsSelected == true){bIsDraging = true;e.Handled = true;}else{bIsDraging = false;}}private void Rectangle_PreviewMouseMove(object sender, MouseEventArgs e){if(bIsDraging){if (Mouse.LeftButton == MouseButtonState.Pressed){if (this.list.SelectedItems.Count>0){//ListBoxItem lstitem = this.list.ItemContainerGenerator.ContainerFromItem(pr) as ListBoxItem;//更新数据//MAx 2013-10-23 16:19:44this.textAdorner.Text = this.list.SelectedItems.Count.ToString();this.gridAdorner.Visibility = Visibility.Visible;DragDropAdorner adorner = new DragDropAdorner(this.gridAdorner);mAdornerLayer = AdornerLayer.GetAdornerLayer(this.list); // Window class do not have AdornerLayer mAdornerLayer.Add(adorner);this.list.Cursor = Cursors.Arrow;string[] files = new string[1];DragDrop.DoDragDrop(list, new DataObject(DataFormats.FileDrop, files), DragDropEffects.Copy | DragDropEffects.Move /* | DragDropEffects.Link */);//DataObject dataObject = new DataObject(files);//System.Windows.DragDrop.DoDragDrop(this.list, dataObject, DragDropEffects.Copy); mAdornerLayer.Remove(adorner);mAdornerLayer = null;this.gridAdorner.Visibility = Visibility.Hidden;}}}}private void Rectangle_PreviewMouseUp(object sender, MouseButtonEventArgs e){bIsDraging = false;}
分别响应PreviewMouseDown,PreviewMouseMove,PreviewMouseUp三个事件
PreviewMouseDown:判断Item是否选为已选择的Item,如果是则进入拖拽状态,标记bIsDraging,并且截断事件e.Handled = true;如果不截断,ListBox会响应点击事件,默认选择当前Item
Rectangle_PreviewMouseMove:如果当前为拖拽状态且鼠标左键按下,则开始拖拽。将gridAdorner作为拖拽预览
Rectangle_PreviewMouseUp:关闭拖拽状态
至此,已经完全实现拖拽多个Item功能。
转载于:https://www.cnblogs.com/max198727/p/3387805.html
WPF MultiSelect模式下ListBox 实现多个ListBoxItem拖拽相关推荐
- wpf mvvm模式下CommandParameter传递多参
wpf mvvm模式下CommandParameter传递多参 原文:wpf mvvm模式下CommandParameter传递多参 CommandParameter一般只允许设置一次,所以如果要传递 ...
- swift 拖动按钮_Swift下使用UICollectionView 实现长按拖拽功能
导读 简单用Swift写了一个collectionview的拖拽点击排序效果; 拖拽排序是新闻类的App可以说是必有的交互设计,如今日头条,网易新闻等. 效果 主要代码 手势长按移动 1.给Colle ...
- swift 选中长按项_Swift下使用UICollectionView 实现长按拖拽功能
导读 简单用Swift写了一个collectionview的拖拽点击排序效果; 拖拽排序是新闻类的App可以说是必有的交互设计,如今日头条,网易新闻等. GitHub地址:https://github ...
- C# WPF MVVM模式下在主窗体显示子窗体并获取结果
01 - 前言 在winform中打开一个新的子窗体很简单,直接实例化窗体并show一下就可以: Form2 f2 = new Form2();f2.Show(); 或者 Form2 f2 = new ...
- WPF MVVM模式下的无阻塞刷新
MVVM模式下的无阻塞刷新的两种方法: //传统模式下的无刷新调用(主线程开新线程,新线程又调用主线程来更新UI) //第1步先在线程内部计算出需要绑定的数据 //第2步然后再使用Invoke/Beg ...
- C# WPF MVVM模式Prism框架下事件发布与订阅
01 - 前言 处理同模块不同窗体之间的通信和不同模块之间不同窗体的通信,Prism提供了一种事件机制,可以在应用程序中低耦合的模块之间进行通信,该机制基于事件聚合器服务,允许发布者和订阅者之间通过事 ...
- C# WPF MVVM模式Caliburn.Micro框架下事件发布与订阅
01 - 前言 处理同模块不同窗体之间的通信和不同模块之间不同窗体的通信,Caliburn提供了一种事件机制,可以在应用程序中低耦合的模块之间进行通信,该机制基于事件聚合器服务,允许发布者和订阅者之间 ...
- C# WPF MVVM模式Prism框架从零搭建(经典)
01 - 前言 目前最新的PRISM的版本是8.1.97,本节以6.3.0.0 讲解,可以在Github上获取PRISM的源码. Prism Github地址:https://github.com/P ...
- WPF随笔(十四)--如何在MVVM模式下关闭窗口
离上一篇WPF随笔有多久,再度编码WPF项目就有多久.机缘巧合又接下了一个开发WPF桌面程序的任务,又有机会详细研究之前一直忽略的细节. 今天就来谈谈如何在MVVM模式下关闭窗口. 什么?关闭窗口还要 ...
最新文章
- JavaScript系统对象
- 预编译 ASP.NET 网站以进行部署
- 2020年AI产业报告:100个岗位抢1个人,计算机视觉成最大缺口
- mysql5.7 cmake源码编译安装
- python基础包括什么-Python基础-数据类型总结归纳.
- Qt下Tcp传输文件
- Asp.net core中Migration工具使用的交流分享
- git提交代码的两种方法步骤
- ascii码值为负数_C语言编程基础学习字符型数据的ASCII码值为何是负数?
- 网络---协议(TCP/IP五层模型)
- Padavan(华硕固件) 伪固定闪讯密码.
- 数组之concat注意事项-不更改原数组
- Android 10 状态栏通知图标和下拉状态栏图标为白色问题
- 最新“3D版”DALL·E爆火,超快速度生成3D点云模型,OpenAI向谷歌新领域发起挑战丨开源...
- kafka文档(3)----0.8.2-kafka API(java版本)
- 首个可用于深度学习的ToF相关数据集——基于置信度的立体相机以及ToF相机深度图融合框架
- 有趣的跳跃(循环判断)
- Mbus新增主动报警功能,简单问题的波折路程。
- 微信公众号获取用户手机
- jenkins占据内存过大
热门文章
- 《孙子兵法》十三篇注译(15--结束语)
- vue vue-cli3 修改elementui的date-picker源码 引入node_modules里的element-ui后报错exports is not defined...
- 记一次 react 15.3.1 老项目升级到 react 16.7.0 之路
- 【.net 深呼吸】在运行阶段修改应用配置文件
- 2015-12-18 学习心得
- 使用MDT2013部署Win8系统之五-配置MDT服务器之添加任务序列
- 在SQL中使用convert函数进行日期的查询
- 奔四的技术人,内心都有哪些波澜?
- Shell命令-关机重启及注销之logout、exit
- JavaWeb学习之Spring框架(一)