本文主要是介绍WPF 通过拖拽改变Item的顺序 ItemsControl,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
拖拽每个元素 移动位置 和点击前后移动位置 要求低一点就点击前后移动位置就够了
之前发过一篇 WPF,strackpanel 拖拽控件 改名,实际上是差不多的,随着对此深入理解可以更加的封装
https://blog.csdn.net/sinat_30224769/article/details/111668459?spm=1001.2014.3001.5501
git链接
https://github.com/442040292/ItemsControlDragSortDemo
基础代码重要
扩展方法
internal static partial class ItemsControlDropSortExtendMethod{//根据子元素查找父元素public static T FindVisualParent<T>(DependencyObject obj) where T : class{while (obj != null){if (obj is T)return obj as T;obj = VisualTreeHelper.GetParent(obj);}return null;}public static bool GetDragItem(this MouseEventArgs e, object sender, out object data){data = null;var pos = e.GetPosition((IInputElement)sender);HitTestResult result = VisualTreeHelper.HitTest((Visual)sender, pos);if (result == null){return false;}var listBoxItem = ItemsControlDropSortExtendMethod.FindVisualParent<FrameworkElement>(result.VisualHit);if (listBoxItem == null){return false;}if (listBoxItem.DataContext == null){return false;}data = listBoxItem.DataContext;return true;}public static bool GetDropItem(this DragEventArgs e, object sender, out object from, out object to){from = null;to = null;var pos = e.GetPosition((IInputElement)sender);var result = VisualTreeHelper.HitTest((Visual)sender, pos);if (result == null){return false;}//查找元数据var sourcePerson = e.Data.GetData(e.Data.GetFormats()[0]);if (sourcePerson == null){return false;}//查找目标数据var listBoxItem = ItemsControlDropSortExtendMethod.FindVisualParent<FrameworkElement>(result.VisualHit);if (listBoxItem == null){return false;}from = sourcePerson;to = listBoxItem.DataContext;return true;}/// <summary>/// 移动列表元素 /// </summary>/// <typeparam name="T"></typeparam>/// <param name="itemSource"></param>/// <param name="fromObj"></param>/// <param name="toObj"></param>/// <param name="pre"></param>public static void ChangeIetmIndex<T>(this Collection<T> itemSource, object fromObj, object toObj, int pre){if (fromObj == null || toObj == null){return;}if (!(fromObj is T) || !(toObj is T)){return;}if (fromObj.Equals(toObj)){return;}var fromItem = (T)fromObj;var toItem = (T)toObj;itemSource.Remove(fromItem);int indexTo = itemSource.IndexOf(toItem);if (indexTo == 0 && pre == 0){itemSource.Insert(0, fromItem);}else if (indexTo == itemSource.Count - 1 && pre == 1){itemSource.Add(fromItem);}else{itemSource.Insert(indexTo + pre, fromItem);}}/// <summary>/// 移动列表元素/// </summary>/// <typeparam name="T"></typeparam>/// <param name="itemSource"></param>/// <param name="itemObj"></param>/// <param name="pre"></param>public static void ChangeIetmIndex<T>(this Collection<T> itemSource, object itemObj, int pre){if (itemObj == null){return;}if (!(itemObj is T)){return;}var item = (T)itemObj;int indexItem = itemSource.IndexOf(item);if (indexItem == 0 && pre == -1){//保持}else if (indexItem == itemSource.Count - 1 && pre == 1){//保持}else{itemSource.Remove(item);itemSource.Insert(indexItem + pre, item);}}}
如何使用
界面部分
<Window x:Class="ItemsControlDragSortDemo.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:ItemsControlDragSortDemo"xmlns:vm="clr-namespace:ItemsControlDragSortDemo"mc:Ignorable="d"Title="MainWindow" Height="450" Width="800"><Window.DataContext><vm:MainWindowViewModel x:Name="MainWindowViewModel"/></Window.DataContext><Window.Resources><Style x:Key="GridMouseOverHighLightStyle" TargetType="{x:Type local:DragGrid}"><Setter Property="Background" Value="#01FFFFFF" /><Style.Triggers><Trigger Property="IsMouseOver" Value="True"><Setter Property="Background" Value="#441AAA5E" /></Trigger><Trigger Property="IsDragMouseOver" Value="True"><Setter Property="Background" Value="#441AAA5E" /></Trigger></Style.Triggers></Style><Style x:Key="GridMouseOverHighLightStyle2" TargetType="{x:Type local:DragGrid}"><Setter Property="Background" Value="#01FFFFFF" /><Style.Triggers><Trigger Property="IsMouseOver" Value="True"><Setter Property="Background" Value="#440000FF" /></Trigger><Trigger Property="IsDragMouseOver" Value="True"><Setter Property="Background" Value="#440000FF" /></Trigger></Style.Triggers></Style></Window.Resources><Grid><ItemsControl x:Name="LBoxSort"ItemsSource="{Binding YouItemSource}"AllowDrop="True"PreviewMouseMove="LBoxSort_OnPreviewMouseMove" ><!--Drop="LBoxSort_OnDrop"--><ItemsControl.ItemTemplate><DataTemplate><Grid Background="Red" Width="60" Height="30" Margin="10" ><TextBlock Text="{Binding Name}"/><Grid><Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition/></Grid.ColumnDefinitions><local:DragGrid Style="{StaticResource GridMouseOverHighLightStyle}" Drop="LBoxSort_Drop_Prev" MouseLeftButtonDown="LBoxSort_Move_Prev" /><local:DragGrid Style="{StaticResource GridMouseOverHighLightStyle2}" Drop="LBoxSort_Drop_Next" MouseLeftButtonDown="LBoxSort_Move_Next" Grid.Column="1"/></Grid></Grid></DataTemplate></ItemsControl.ItemTemplate><ItemsControl.ItemsPanel><ItemsPanelTemplate><WrapPanel /></ItemsPanelTemplate></ItemsControl.ItemsPanel></ItemsControl></Grid>
</Window>
界面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.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;namespace ItemsControlDragSortDemo
{/// <summary>/// Interaction logic for MainWindow.xaml/// </summary>public partial class MainWindow : Window{public MainWindow(){InitializeComponent();}public MainWindowViewModel ViewModel { get => this.DataContext as MainWindowViewModel; }private void LBoxSort_OnPreviewMouseMove(object sender, MouseEventArgs e){if (e.LeftButton == MouseButtonState.Pressed){e.GetDragItem(sender, out object from);DragDrop.DoDragDrop(LBoxSort, from, DragDropEffects.Move);}}private void LBoxSort_Drop_Prev(object sender, DragEventArgs e){var success = e.GetDropItem(sender, out object from, out object to);if (success){ViewModel.ChangeIetmIndex(from, to, 0);}}private void LBoxSort_Drop_Next(object sender, DragEventArgs e){var success = e.GetDropItem(sender, out object from, out object to);if (success){ViewModel.ChangeIetmIndex(from, to, 1);}}private void LBoxSort_Move_Prev(object sender, MouseButtonEventArgs e){var control = sender as FrameworkElement;var dc = control.DataContext;ViewModel.ChangeIetmIndex(dc, -1);}private void LBoxSort_Move_Next(object sender, MouseButtonEventArgs e){var control = sender as FrameworkElement;var dc = control.DataContext;ViewModel.ChangeIetmIndex(dc, 1);}}
}
viewmodel 调用
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace ItemsControlDragSortDemo
{public class MainWindowViewModel : ViewModelBase{public MainWindowViewModel(){List<YouItemViewModel> list = new List<YouItemViewModel>();for (int i = 0; i < 10; i++){list.Add(new YouItemViewModel { Name = "" + i });}YouItemSource = new ObservableCollection<YouItemViewModel>(list);}private ObservableCollection<YouItemViewModel> _YouItemSource;public ObservableCollection<YouItemViewModel> YouItemSource { get => _YouItemSource; set => Set(ref _YouItemSource, value); }public class YouItemViewModel{public string Name { get; set; }}#region 拖拽移动顺序public void ChangeIetmIndex(object from, object to, int pre){YouItemSource.ChangeIetmIndex(from, to, pre);}public void ChangeIetmIndex(object item, int pre){YouItemSource.ChangeIetmIndex(item, pre);}#endregion}
}
viewmodel 基础类
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;namespace ItemsControlDragSortDemo
{public class ViewModelBase : NotifyPropertyBase{}public class NotifyPropertyBase : INotifyPropertyChanged{public event PropertyChangedEventHandler PropertyChanged;protected virtual bool Set<T>(ref T storage, T value, [CallerMemberName] string propertyName = null){if (object.Equals(storage, value)) return false;storage = value;this.OnPropertyChanged(propertyName);return true;}protected void OnPropertyChanged(string propertyName){this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));}}
}
另外拖拽的时候是没有mouseover效果的 所以 对Grid 做了一点调整 可以把这一段代码直接写在cs 也可以 重新搞个控件 我这里是重新搞控件继承了一下
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;namespace ItemsControlDragSortDemo
{public class DragGrid : Grid{public bool IsDragMouseOver{get { return (bool)GetValue(IsDragMouseOverProperty); }set { SetValue(IsDragMouseOverProperty, value); }}// Using a DependencyProperty as the backing store for IsDragMouseOver. This enables animation, styling, binding, etc...public static readonly DependencyProperty IsDragMouseOverProperty =DependencyProperty.Register("IsDragMouseOver", typeof(bool), typeof(DragGrid), new PropertyMetadata(false));protected override void OnDragEnter(DragEventArgs e){base.OnDragEnter(e);IsDragMouseOver = true;}protected override void OnDragLeave(DragEventArgs e){base.OnDragLeave(e);IsDragMouseOver = false;}protected override void OnDragOver(DragEventArgs e){base.OnDragOver(e);IsDragMouseOver = true;}protected override void OnDrop(DragEventArgs e){base.OnDrop(e);IsDragMouseOver = false;}}
}
这样的话就能满足 拖拽每个元素 移动位置 和点击前后移动位置 要求低一点就点击前后移动位置就够了
这篇关于WPF 通过拖拽改变Item的顺序 ItemsControl的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!