Silverlight4不同控件间拖拽实现-附源码下载

前天整理一份Silverlight 4中拖拽效果实现-附源码下载  在评论中一位园友提到实现不同控件间拖拽效果设想. 其实在项目中原本我遇到最初拖拽实现就是一个从TreeView中拖拽到一个ListBox中.中午正好看了Silverlight.net BBS和CrraySun.com上讨论.做了一个简单Demo实现.先看看效果:

  Get Microsoft Silverlight

左边Listbox,右边Treeview.实现步骤如下

A:页面布局:

ExpandedBlockStart.gif 代码
 1     < Grid  x:Name ="LayoutRoot"  Background ="White"    HorizontalAlignment ="Center"  VerticalAlignment ="Center" >
 2           < Grid.RowDefinitions >
 3               < RowDefinition  Height ="40" ></ RowDefinition >
 4               < RowDefinition  Height ="350" ></ RowDefinition >
 5               < RowDefinition  Height ="10*"   />
 6           </ Grid.RowDefinitions >
 7           < Grid.ColumnDefinitions >
 8               < ColumnDefinition  Width ="300" ></ ColumnDefinition >
 9               < ColumnDefinition  Width ="300" ></ ColumnDefinition >
10               < ColumnDefinition  Width ="200*"   />
11           </ Grid.ColumnDefinitions >
12          
13           < TextBlock  Text ="Drag  Listbox to Treeview"  Foreground ="Red"  FontFamily ="Comic Sans MS"  FontSize ="16"  Grid.ColumnSpan ="2"  Margin ="85,12,162,0" ></ TextBlock >
14           <!-- 左边一个listBox -->
15           < toolKit:ListBoxDragDropTarget  AllowDrop ="True"  Grid.Row ="1"  Grid.Column ="0"   >
16               < ListBox  x:Name ="customerListBoxMain"  Height ="240"  Width ="215"  SelectionMode ="Extended"    DisplayMemberPath ="CustomerName"  BorderBrush ="Black"  BorderThickness ="1" >
17                   < ListBox.ItemsPanel >
18                       < ItemsPanelTemplate >
19                           < StackPanel  Orientation ="Vertical" />
20                       </ ItemsPanelTemplate >
21                   </ ListBox.ItemsPanel >
22               </ ListBox >
23 
24           </ toolKit:ListBoxDragDropTarget >
25          
26           <!-- 右边一个Treeview -->
27           < toolKit:TreeViewDragDropTarget  AllowDrop ="True"  Grid.Row ="1"  Grid.Column ="1"  BorderThickness ="1"  BorderBrush ="Red" >
28               <!-- 定义一个数据模板 -->
29               < toolKit:TreeViewDragDropTarget.Resources >
30                   < my:HierarchicalDataTemplate  x:Name ="datetmp"  ItemsSource =" {Binding Customer} " >
31                       < TextBlock  Text =" {Binding CustomerName} " />
32                   </ my:HierarchicalDataTemplate >
33               </ toolKit:TreeViewDragDropTarget.Resources >
34               < sdk:TreeView  x:Name ="AcceptTreeview"  Height ="240"  Width ="215"  ItemTemplate =" {StaticResource datetmp} " >   </ sdk:TreeView >
35              
36           </ toolKit:TreeViewDragDropTarget >
37       </ Grid >

同上篇不同在TreeView中使用到了HierarchicalDataTemplate数据模板来定义Treeview数据显示. HierarchicalDataTemplate 数据模板默认是不添加的, 所以需要在页面添加引用如下:

1      xmlns:my="clr-namespace:System.Windows;assembly=System.Windows.Controls"

至于HierarchicalDataTemplate如何使用请参见MSDN.

B:数据绑定-后台代码

同样为了演示方便 直接写了一个类用来ListBox和Treeview中提供所需数据. 

ExpandedBlockStart.gif 代码
 1    ///   <summary>
 2       ///  为了达到演示目的 当前类提供list数据
 3       ///  Author:chenkai Date:2010年5月28日10:21:36
 4       ///   </summary>
 5       public   class  ProvideDate
 6      {
 7           public   static  List < Customer >  GetAllCustomerList()
 8          {
 9              List < Customer >  getcuslist  =   new  List < Customer > ();
10              getcuslist.Add( new  Customer { CustomerName = " JackChen "  });
11              getcuslist.Add( new  Customer { CustomerName  =   " Arrmy "  });
12              getcuslist.Add( new  Customer { CustomerName  =   " SunSkyUnion "  });
13              getcuslist.Add( new  Customer { CustomerName  =   " 西藏拉萨 "  });
14              getcuslist.Add( new  Customer { CustomerName  =   " 甘肃玉门关 "  });
15 
16               return  getcuslist;
17          }
18 
19 
20           public   static  List < Customer >  GetAllCustomerTreeList()
21          {
22              List < Customer >  getcuslist  =   new  List < Customer > ();
23              getcuslist.Add( new  Customer { CustomerName  =   " markChen "  });
24              getcuslist.Add( new  Customer { CustomerName  =   " KaiDun "  });
25              getcuslist.Add( new  Customer { CustomerName  =   " GuideInformation "  });
26              getcuslist.Add( new  Customer { CustomerName  =   " 三门峡函谷关 "  });
27              getcuslist.Add( new  Customer { CustomerName  =   " 嘉峪关 "  });
28              getcuslist.Add( new  Customer { CustomerName  =   " 泰山 "  });
29              getcuslist.Add( new  Customer { CustomerName  =   " 嵩山 "  });
30 
31               return  getcuslist;
32          }
33      }
34 
35       public   class  Customer
36      {
37           public   string  CustomerName {  get set ; }
38      }

 页面数据绑定: 

ExpandedBlockStart.gif 代码
 1     // 绑定ListBox数据
 2              List < Customer >  getcuslist  =  TestSilverlightOutOfBrowerDemo.Date.ProvideDate.GetAllCustomerList();
 3               if  (getcuslist  !=   null )
 4              {
 5                  ObservableCollection < Customer >  getlist  =   new  ObservableCollection < Customer > ();
 6                   foreach  (Customer getcus  in  getcuslist)
 7                  {
 8                      getlist.Add(getcus);
 9                  }
10                   this .customerListBoxMain.ItemsSource  =  getlist;
11              }
12 
13               // 绑定Treeview数据
14              List < Customer >  gettreeviewlist = TestSilverlightOutOfBrowerDemo.Date.ProvideDate.GetAllCustomerTreeList();
15              ObservableCollection < Customer >  getviewlist  =   new  ObservableCollection < Customer > ();
16               foreach  (Customer getcustree  in  gettreeviewlist)
17               {
18                  getviewlist.Add(getcustree);
19               }
20 
21               this .AcceptTreeview.ItemsSource  =  getviewlist;
22              

 因为使用ObservableCollection一个动态数据集合,需要在添加一个空间引用:
1  using  System.Collections.ObjectModel;

ObservableCollection动态数据集合,这次数据通过绑定来实现.动态数据集合,在添加项、移除项或刷新整个列表时,此集合将提供通知 具体参见:MSDN 

如上即简单实现了一个listbox向一个TreeView中拖拽实现,其实我当初在实现这问题,参考大量资料. 我想说一下个人对这个拖拽实现思路理解.首先我想说的是在整个拖拽过程事件执行过程,

注意:虽然实现了Treeview在Listbox之间拖拽,但真正拖拽事件发生是在TreeViewDragDropTarget和ListBoxDragDropTarget控件中. 不要误认为是ListBox或Treeview本身.

(1)先看看TreeViewDragDropTarget关于Drag事件.

分别为Drop,DragOver, DragLeave,DragEnter. 这三个真正执行顺序如下: 

 

 执行场景:当把一个Listbox一个项拖拽到Treeview时 从DragEnter开始执行到DragOver. 其实上面实现完全是利用数据模板和DragDropTraget控件便利. 来整理一下在Sl3.0中实现一个拖拽需要具体步骤拆分:

A:实现一个拖动图像,作为开始拖拽时的快照

B:找到程序的root visual根视觉(如StackPanel) 

C:将拖动图像添加到根视觉,并得到它的绝对坐标[动态坐标数据-难点]

D:在运动时保持鼠标与拖动图像同步,随时给出是否在落下目标(drop target)上的视觉反馈 [需要动画效果]

E:处理用户释放鼠标时刻,当经过落下目标时可以适当地动作,甚至可以显示一段不错的动画

如此就在Silverlight 3.0拖拽效果.当然在4.0加以封装来实现.如何来获得拖拽实时数据 和SL3.0有点不同.

(2)获得拖拽实时数据

其实拖拽时listBox中数据都放在ItemContainer数据容器中,当拖拽一项时既是反映到ItemContainer中就是Remove删除一项,反而言之 接受一方Treeview中数据容器这是Add添加一个新项. 这就给我们提供一个监听拖拽数据机会.我们可以在listbox中ItemContainerGenerator.ItemsChanged定义一个监听事件. 来获取当前拖拽项.

1               // 附属一个监听事件 ItemsChanged 事件由 IItemContainerGenerator 引发,以通知布局项集合已更改
2               this .AcceptTreeview.ItemContainerGenerator.ItemsChanged  +=   new  System.Windows.Controls.Primitives.ItemsChangedEventHandler(ItemContainerGenerator_ItemsChanged);

事件实现:

 1       void  ItemContainerGenerator_ItemsChanged( object  sender, System.Windows.Controls.Primitives.ItemsChangedEventArgs e)
 2          {
 3               if  (e.Action  ==  System.Collections.Specialized.NotifyCollectionChangedAction.Add)
 4              {
 5                   // e.Position获取集合中更改发生的位置
 7                   int  index  =  (e.Position.Index  +  e.Position.Offset);
 8                  MessageBox.Show( " total: "   +   this .AcceptTreeview.Items.Count.ToString()  +   " Index: "   +  index.ToString());
 9                   object  obj  =   this .AcceptTreeview.Items[index];
10 
11                   if  (obj  !=   null )
12                  {
13                      TreeViewItem getitem  =  obj  as  TreeViewItem;
14                      MessageBox.Show(getitem.Header.ToString());
15 
16                      ListBoxItem getboxitem  =  obj  as  ListBoxItem;
17                      MessageBox.Show(getboxitem.Content.ToString());
18                  }
19              }
20          }

通过附属的ItemsChangedEventArgs 附带事件信息. 来判断当前对数据容器ItemContainer操作类型,System.Collections.Specialized.NotifyCollectionChangedAction是一个操作枚举. 包含None Add REmove. 判断拖拽状态后即可通过E.Position来获取数据项发生的位置. 集合通过装换获得具体拖拽项.当然也可定义其他操作. 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值