900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > WPF MultiSelect模式下ListBox 实现多个ListBoxItem拖拽

WPF MultiSelect模式下ListBox 实现多个ListBoxItem拖拽

时间:2024-05-19 14:20:41

相关推荐

WPF MultiSelect模式下ListBox 实现多个ListBoxItem拖拽

WPF 的ListBox不支持很多常见的用户习惯,如在Explorer中用鼠标可以选择多项Item,并且点击已经选择的Item,按住鼠标左键可以将所有已选择Item拖拽到指定的位置。本文简单的实现了这一功能。

效果图:

拖拽1个Item

拖拽多个Item

说明:

代码下载地址:/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 -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功能。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。