WPF实现Drag/Drop操作

时间:2022-11-12 14:26:19
原文: WPF实现Drag/Drop操作

有时候我们方便用户操作,总会把一下Copy/Paste 或者 input操作转换为Drag/Drop, WPF 跟之前WinForm 一样提供了一些实现方式方便开发人员进行开发。

要允许控件Drop操作,首先必须设置控件属性AllowDrop,这样控件才能产生DragOver/DragEnter/Drop等相关事件,从而开发人员可以做一些逻辑判断,设置DragEventArgs 的属性Effects 决定Drag的内容是否允许Drop. 下面是一个简单的例子:

创建两个ListBox, 一个里面有内容(名字为:EmployeeSource),另外一个(名字:SelectedEmployees)没有内容,允许用户从EmployeeSource 拖拽内容到SelectedEmployees。

1. 在Xaml中创建这两个ListBox, 并进行相关数据绑定

        <ListBox x:Name="SelectedEmployees" HorizontalAlignment="Left" Height="100" Margin="35,30,0,0" 
                 ItemsSource="{Binding SelectedEmployeeData}" DisplayMemberPath="Description" 
                 VerticalAlignment="Top" Width="275" AllowDrop="True" 
                 Drop="SelectedEmployees_Drop" DragOver="SelectedEmployees_DragOver" DragLeave="SelectedEmployees_DragLeave" 
                 MouseMove="SelectedEmployees_MouseMove"/>
	<ListBox x:Name="EmployeeSource" DataContext="{Binding Source={StaticResource EmployeeList}}" 
                 SelectionMode="Single" HorizontalAlignment="Left" Height="100" Margin="35,255,0,0" VerticalAlignment="Top" Width="280" 
                 ItemsSource="{Binding Employees}" DisplayMemberPath="Description" MouseMove="EmployeeSource_MouseMove"/>
2. 在cs文件中实现相关事件函数

        bool bMouseDown = true;
        private void EmployeeSource_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
        {
        	// TODO: Add event handler implementation here.
            bMouseDown = e.LeftButton == MouseButtonState.Pressed;
            if (EmployeeSource.SelectedItems.Count == 0 || !bMouseDown)
                return;
            ICollection<EmployeesItem> selected = new List<EmployeesItem>();
            foreach(var item in EmployeeSource.SelectedItems)
            {
                var employee = item as EmployeesItem;
                if (employee == null)
                    return;
                selected.Add(employee);
            }
            DragDrop.DoDragDrop(EmployeeSource, selected, DragDropEffects.Copy);
        }

        private void SelectedEmployees_Drop(object sender, System.Windows.DragEventArgs e)
        {
        	// TODO: Add event handler implementation here.
            var ems = e.Data.GetData(typeof(List<EmployeesItem>)) as List<EmployeesItem>;
            if (ems == null)
                return;
            
            foreach(var em in ems)
            {
                SelectedEmployeeData.Add(em);
            }
        }

        private void SelectedEmployees_DragOver(object sender, System.Windows.DragEventArgs e)
        {
        	// TODO: Add event handler implementation here.
            var ems = e.Data.GetData(typeof(List<EmployeesItem>)) as List<EmployeesItem>;
            if (ems == null)
            {
                e.Effects = DragDropEffects.None;
                return;
            }
            DragElement = ems[0];
            e.Effects = DragDropEffects.Copy;
        }

3. 增加DataContext(ViewModel), 设置绑定的属性

	public class EmployeeList : INotifyPropertyChanged
	{
		public event PropertyChangedEventHandler PropertyChanged;

		protected virtual void OnPropertyChanged(string propertyName)
		{
			if (this.PropertyChanged != null)
			{
				this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
			}
		}

		public EmployeeList()
		{
			try
			{
				Uri resourceUri = new Uri("/WPFStudy;component/SampleData/EmployeeList/EmployeeList.xaml", UriKind.RelativeOrAbsolute);
				System.Windows.Application.LoadComponent(this, resourceUri);
			}
			catch
			{
			}
		}

		private Employees _Employees = new Employees();

		public Employees Employees
		{
			get
			{
				return this._Employees;
			}
		}
	}

	public class EmployeesItem : INotifyPropertyChanged
	{
		public event PropertyChangedEventHandler PropertyChanged;

		protected virtual void OnPropertyChanged(string propertyName)
		{
			if (this.PropertyChanged != null)
			{
				this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
			}
		}

        public override bool Equals(object obj)

        {

            var tmp = obj as EmployeesItem;

            if (tmp == null) return false;

            return tmp.Description.Equals(Description);

        }


		private string _Description = string.Empty;

		public string Description
		{
			get
			{
				return this._Description;
			}

			set
			{
				if (this._Description != value)
				{
					this._Description = value;
					this.OnPropertyChanged("Description");
				}
			}
		}
	}

	public class Employees : System.Collections.ObjectModel.ObservableCollection<EmployeesItem>
	{ 
	}