拖拽每个元素 移动位置 和点击前后移动位置 要求低一点就点击前后移动位置就够了
之前发过一篇 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;
}
}
}
这样的话就能满足 拖拽每个元素 移动位置 和点击前后移动位置 要求低一点就点击前后移动位置就够了
版权声明:本文为sinat_30224769原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。