您的位置:首页 > 运维架构

在WPF中通过DataTemple实现Drag&Drop控件

2011-04-13 19:33 387 查看
WPF中提供一套十分简便的实现Drag&Drop的机制,方便了开发人员定制自己的Drag&Drop行为。

但是WPF中提供的Drag&Drop是基于数据传递的,通过Drag把你希望传递的数据放入DataObject对象里, 调用DragDrop.DoDragDrop(), 在Drop事件Hander里就可以获取到你刚才传入的数据,在使对这些数据做处理就完成了整个Drag&Drop行为。

实际中经常用到拖拽控件本身,这在WPF中怎么实现呢?笔者想到可以利用WPF中的DataTemple, DataTemple定义了用来展现数据的界面模板,你可以想象即使在界面层,你操作控制的也是一堆数据,这些数据的展现交给DataTemplate来做。那还等什么,利用它来实现Drag&Drop控件吧。

下面是我的一个Sample, 供大家参考:

1.首先定义PresenterDataForButton和PresenterDataForTextBox 分别代表 Button 和TextBox控件的Data类型:

1 public interface ITragable
2 {
3 }
4 public class PresenterDataForButton :ITragable
5 {
6 public string Content
7 {
8 get;
9 set;
10 }
11
12 public RoutedEventHandler ButtonClickHandler;
13
14 }
15
16 public class PresenterDataForTextBox : ITragable
17 {
18 public string Text
19 {
20 get;
21 set;
22 }
23 }

2. 利用DataTemple使数据分别展现成Button和TextBox控件,注意本例中DataTemple的定义是放在Window的Resouce中,并且是使用的是DataType,这样整个window中的PresenterDataForButton和PresenterDataForTextBox 都会被展现成相应的控件:

1 <Window x:Class="MyDragAndDrop.MainWindow"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 xmlns:local="clr-namespace:MyDragAndDrop"
5 Title="MainWindow" Height="350" Width="525">
6 <Window.Resources>
7
8 <DataTemplate DataType="{x:Type local:PresenterDataForButton}">
9 <Button Content="{Binding Path=Content}"/>
10 </DataTemplate>
11 <DataTemplate DataType="{x:Type local:PresenterDataForTextBox}">
12 <TextBox Text="{Binding Path=Text}"/>
13 </DataTemplate>
14
15 </Window.Resources>
16 <DockPanel >
17 <ListView x:Name="listView" DockPanel.Dock="Left"
18 PreviewMouseLeftButtonDown="listView_PreviewMouseLeftButtonDown"
19 PreviewMouseMove="listView_PreviewMouseMove"/>
20 <Canvas Drop="ContentControl_Drop" DockPanel.Dock="Right"
21 AllowDrop="True" Background="LightBlue"
22 DragEnter="ContentControl_DragEnter" Height="260" Width="272">
23 <StackPanel x:Name="myStackPanel"/>
24
25 </Canvas>
26 </DockPanel>
27
28 </Window>
3. 最后通过Drag&Drop你的数据,达到拖拽控件的效果。

View Code

1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Windows;
6 using System.Windows.Controls;
7 using System.Windows.Data;
8 using System.Windows.Documents;
9 using System.Windows.Input;
10 using System.Windows.Media;
11 using System.Windows.Media.Imaging;
12 using System.Windows.Navigation;
13 using System.Windows.Shapes;
14
15 namespace MyDragAndDrop
16 {
17 /// <summary>
18 /// Interaction logic for MainWindow.xaml
19 /// </summary>
20 public partial class MainWindow : Window
21 {
22 private Point m_startPoint;
23
24 public MainWindow()
25 {
26 InitializeComponent();
27 this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
28 }
29
30
31 private void MainWindow_Loaded(object sender, RoutedEventArgs e)
32 {
33
34 this.listView.Items.Add(new PresenterDataForButton
35 {
36 Content = "Click Me",
37 ButtonClickHandler = (object sender1, RoutedEventArgs e1) =>
38 {
39 MessageBox.Show("Clicked");
40 }
41 });
42
43 this.listView.Items.Add(new PresenterDataForTextBox { Text = "It is a TextBox." });
44
45 }
46
47 private void listView_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
48 {
49 m_startPoint = e.GetPosition(null);
50
51 }
52
53 private void listView_PreviewMouseMove(object sender, MouseEventArgs e)
54 {
55 // Get the current mouse position
56 Point mousePos = e.GetPosition(null);
57 Vector diff = m_startPoint - mousePos;
58
59 if (e.LeftButton == MouseButtonState.Pressed &&
60 Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
61 Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance)
62 {
63 // Get the dragged ListViewItem
64 ListView listView = sender as ListView;
65 if (null != listView)
66 {
67
68 ListViewItem listViewItem =
69 FindAnchestor<ListViewItem>((DependencyObject)e.OriginalSource);
70
71 if (null != listViewItem)
72 {
73
74 // Find the data behind the ListViewItem
75 object dragedObject = listView.ItemContainerGenerator.
76 ItemFromContainer(listViewItem);
77
78 // Initialize the drag & drop operation
79 DataObject dragData = new DataObject("myFormat", dragedObject);
80 DragDrop.DoDragDrop(listViewItem, dragData, DragDropEffects.Move);
81 }
82 }
83 }
84
85 }
86
87
88 // Helper to search up the VisualTree
89 private static T FindAnchestor<T>(DependencyObject current)
90 where T : DependencyObject
91 {
92 do
93 {
94 if (current is T)
95 {
96 return (T)current;
97 }
98 current = VisualTreeHelper.GetParent(current);
99 }
100 while (current != null);
101 return null;
102 }
103
104 private void ContentControl_Drop(object sender, DragEventArgs e)
105 {
106 if (e.Data.GetDataPresent("myFormat"))
107 {
108 ITragable dragedObject = e.Data.GetData("myFormat") as ITragable;
109 if(null!=dragedObject)
110 {
111 Canvas canvas = sender as Canvas;
112 var content = new ContentControl();
113 content.Content = dragedObject;
114 myStackPanel.Children.Add(content);
115 }
116 }
117
118 }
119
120 private void ContentControl_DragEnter(object sender, DragEventArgs e)
121 {
122 if (!e.Data.GetDataPresent(typeof(ITragable)) ||
123 sender == e.Source)
124 {
125 e.Effects = DragDropEffects.None;
126 }
127
128
129 }
130
131
132
133 }
134 }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: