zoukankan      html  css  js  c++  java
  • Silverlight4不同控件间拖拽实现附源码下载

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

      Get Microsoft Silverlight

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

    A:页面布局:

    代码
     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中提供所需数据. 

    代码
     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 { getset; }
    38     }

     页面数据绑定: 

    代码
     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来获取数据项发生的位置. 集合通过装换获得具体拖拽项.当然也可定义其他操作. 

  • 相关阅读:
    Apache Ant 1.9.1 版发布
    Apache Subversion 1.8.0rc2 发布
    GNU Gatekeeper 3.3 发布,网关守护管理
    Jekyll 1.0 发布,Ruby 的静态网站生成器
    R语言 3.0.1 源码已经提交到 Github
    SymmetricDS 3.4.0 发布,数据同步和复制
    beego 0.6.0 版本发布,Go 应用框架
    Doxygen 1.8.4 发布,文档生成工具
    SunshineCRM 20130518发布,附带更新说明
    Semplice Linux 4 发布,轻量级发行版
  • 原文地址:https://www.cnblogs.com/chenkai/p/1746559.html
Copyright © 2011-2022 走看看