winfwu

导航

WPF SurfaceListbox拖拽事件 之一(SurfaceListbox To SurfaceListbox篇)

效果图:

 

(1)    DataItem类的用于创建项目SurfaceListBox控制。它有两个属性:

Name:Item

CanDrop: 指定的项目是否可以删除目标控制

 
public class DataItem
    {
        private string name;
        private bool canDrop;
 
        public string Name
        {
            get { return name; }
        }
 
        public bool CanDrop
        {
            get { return canDrop; }
        }
 
        public DataItem(string name, bool canDrop)
        {
            this.name = name;
            this.canDrop = canDrop;
        }
    }

 

(2)    DataTemplate对象(数据外衣)指定每个项目的布局,并将Name属性和CanDrop属性的内容两个相应的标签控件。

 

<s:SurfaceWindow x:Class="DraggingAndDroppingBetweenSurfaceListBoxes.SurfaceWindow1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:s="http://schemas.microsoft.com/surface/2008"
    Title="DraggingAndDroppingBetweenSurfaceListBoxes"
    >
 
    <s:SurfaceWindow.Resources>
        
        <DataTemplate x:Key="SurfaceListBoxItemDataTemplate">
            <StackPanel Height="120" Width="190" Background="Gray">
                    <Label 
                        Content="{Binding Name}" 
                        HorizontalAlignment="Center" 
                        VerticalAlignment="Center"
                        FontSize="20"/>
 
                    <Label 
                        Content="{Binding CanDrop}"
                        HorizontalAlignment="Center" 
                        VerticalAlignment="Center"
                        FontSize="18"/>
                </StackPanel>
        </DataTemplate>
    </s:SurfaceWindow.Resources>
 
    <Grid>
    </Grid>
    
</s:SurfaceWindow>
 

(3)    两个ObservableCollection对象来保存数据项定义。这个集合是暴露通过公共属性,定义在后台代码文件为主要SurfaceWindow对象。

sourceItems: Item数据源列表框

TargetItems: Item拖放至列表框

注意:需要引用using System.Collections.ObjectModel;
 
        private ObservableCollection<DataItem> sourceItems;
        private ObservableCollection<DataItem> targetItems;
 
        /// <summary>
        /// Items that bind with the drag source list box.
        /// </summary>
        public ObservableCollection<DataItem> SourceItems
        {
            get
            {
                if (sourceItems == null)
                {
                    sourceItems = new ObservableCollection<DataItem>();
                }
 
                return sourceItems;
            }
        }
 
        /// <summary>
        /// Items that bind with the drop target list box.
        /// </summary>
        public ObservableCollection<DataItem> TargetItems
        {
            get
            {
                if (targetItems == null)
                {
                    targetItems = new ObservableCollection<DataItem>();
                }
 
                return targetItems;
            }
        }
 
    }

(4)     初始化数据(向SourceItem集合中添加DataItem项)

 

protected override void OnInitialized(EventArgs e)
        {
            base.OnInitialized(e);
            DataContext = this;
            SourceItems.Add(new DataItem("Hammer", false));
            SourceItems.Add(new DataItem("Saw", true));
            SourceItems.Add(new DataItem("Pliers", true));
            SourceItems.Add(new DataItem("Tape Measure", false));
            SourceItems.Add(new DataItem("Square", true));
            SourceItems.Add(new DataItem("Wrench", false));
            SourceItems.Add(new DataItem("Screwdriver", true));
            SourceItems.Add(new DataItem("Plumb Bob", true));
            SourceItems.Add(new DataItem("Miter Box", false));
            SourceItems.Add(new DataItem("Knife", true));
            SourceItems.Add(new DataItem("Chisel", true));
            SourceItems.Add(new DataItem("Punch", true));
        }

(5)    创建SurfaceListBox控制和绑定的物品

DragSource:被拖拽SurfaceListbox集合

DropTarget:被放置的surfaceListBox集合

重点是:PreviewTouchDown事件和SurfaceDragDrop的四个事件:DragCompleted,DragEnter,DragLeave,Drop

<Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <s:SurfaceListBox 
            Name="DragSource" 
            Grid.Column="0"
            Width="250"
            BorderBrush="{DynamicResource {x:Static s:SurfaceColors.ListBoxItemBackgroundBrushKey}}"
            ItemTemplate="{StaticResource SurfaceListBoxItemDataTemplate}"
            ItemsSource="{Binding Path=SourceItems}"
            PreviewTouchDown="OnDragSourcePreviewTouchDown"
            s:SurfaceDragDrop.DragCompleted="OnDragCompleted"/>
 
        <s:SurfaceListBox 
            Name="DropTarget" 
            Grid.Column="1"
            AllowDrop="True"
            Width="250"
            BorderBrush="{DynamicResource {x:Static s:SurfaceColors.ListBoxItemBackgroundBrushKey}}"
            ItemTemplate="{StaticResource SurfaceListBoxItemDataTemplate}"
            ItemsSource="{Binding Path=TargetItems}"
            s:SurfaceDragDrop.DragEnter="OnDropTargetDragEnter"
            s:SurfaceDragDrop.DragLeave="OnDropTargetDragLeave"
            s:SurfaceDragDrop.Drop="OnDropTargetDrop"/>
    </Grid>

 

 

 

(6)    CarsorStyle(光标风格设置)目标对象被选中时边框颜色为黄色。拖动目标对象之另外一个surfaceListbox对象中呈现绿色说明可以被放入,呈现红色说明不能不放入。

<Style x:Key="CursorStyle" TargetType="{x:Type ContentControl}">
            <Setter Property="ContentTemplate" Value="{StaticResource SurfaceListBoxItemDataTemplate}" />
            <Setter Property="BorderThickness" Value="9"/>
            <Setter Property="BorderBrush" Value="{DynamicResource {x:Static s:SurfaceColors.Accent1BrushKey}}"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ContentControl}">
                        <Border 
                            BorderThickness="{TemplateBinding BorderThickness}" 
                            BorderBrush="{TemplateBinding BorderBrush}">
                            <ContentPresenter Margin="0"
                                Content="{TemplateBinding Content}" 
                                ContentTemplate="{TemplateBinding ContentTemplate}">
                            </ContentPresenter>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <Trigger Property="Tag" Value="CanDrop">
                    <Setter Property="BorderBrush" Value="{DynamicResource {x:Static s:SurfaceColors.Accent4BrushKey}}" />
                </Trigger>
                <Trigger Property="Tag" Value="CannotDrop">
                    <Setter Property="BorderBrush" Value="{DynamicResource {x:Static s:SurfaceColors.Accent3BrushKey}}" />
                </Trigger>
            </Style.Triggers>
        </Style>

(7)    PreviewTouchDown事件

详细见代码内部文档注释:

private void OnDragSourcePreviewTouchDown(object sender, TouchEventArgs e)
        {
               //获取当前触摸对象转换成FrameworkElement
            FrameworkElement findSource = e.OriginalSource as FrameworkElement;
               //new一个draggedElement初始化为null
            SurfaceListBoxItem draggedElement = null;
 
            // Find the touched SurfaceListBoxItem object.
            while (draggedElement == null && findSource != null)
            {
                if ((draggedElement = findSource as SurfaceListBoxItem) == null)
                {
                    findSource = VisualTreeHelper.GetParent(findSource) as FrameworkElement;
                }
            }
 
            if (draggedElement == null)
            {
                return;
            }
 
            // Create the cursor visual.
            ContentControl cursorVisual = new ContentControl()
            {
                Content = draggedElement.DataContext,
                Style = FindResource("CursorStyle") as Style
            };
 
            // Add a handler. This will enable the application to change the visual cues.
            SurfaceDragDrop.AddTargetChangedHandler(cursorVisual, OnTargetChanged);
 
            // Create a list of input devices. Add the touches that
            // are currently captured within the dragged element and
            // the current touch (if it isn't already in the list).
            List<InputDevice> devices = new List<InputDevice>();
            devices.Add(e.TouchDevice);
            foreach (TouchDevice touch in draggedElement.TouchesCapturedWithin)
            {
                if (touch != e.TouchDevice)
                {
                    devices.Add(touch);
                }
            }
 
            // Get the drag source object
            ItemsControl dragSource = ItemsControl.ItemsControlFromItemContainer(draggedElement);  
 
            SurfaceDragCursor startDragOkay =
                SurfaceDragDrop.BeginDragDrop(
                  dragSource,                 // The SurfaceListBox object that the cursor is dragged out from.
                  draggedElement,             // The SurfaceListBoxItem object that is dragged from the drag source.
                  cursorVisual,               // The visual element of the cursor.
                  draggedElement.DataContext, // The data associated with the cursor.
                  devices,                    // The input devices that start dragging the cursor.
                  DragDropEffects.Move);      // The allowed drag-and-drop effects of the operation.
 
            // If the drag began successfully, set e.Handled to true. 
            // Otherwise SurfaceListBoxItem captures the touch 
            // and causes the drag operation to fail.
            e.Handled = (startDragOkay != null);
        }

(8)    DragEnter事件

private void OnDropTargetDragEnter(object sender, SurfaceDragDropEventArgs e)
        {
               //获取DataItem类数据
            DataItem data = e.Cursor.Data as DataItem;
               //获取CanDrop中的值
            if (!data.CanDrop)
            {
               //不能被放置到拖动的集合中            
                e.Effects = DragDropEffects.None;
            }
        }

(9)    DragLeave事件

private void OnDropTargetDragLeave(object sender, SurfaceDragDropEventArgs e)
        {
            // Reset the effects.
            e.Effects = e.Cursor.AllowedEffects;
        }

(10)OnTargetChanged方法(PreviewTouchDown调用了该方法)

private void OnTargetChanged(object sender, TargetChangedEventArgs e)
        {
            if (e.Cursor.CurrentTarget != null)
            {
                DataItem data = e.Cursor.Data as DataItem;
                e.Cursor.Visual.Tag = (data.CanDrop) ? "CanDrop" : "CannotDrop";
            }
            else
            {
                e.Cursor.Visual.Tag = null;
            }
        }
 

(11) Drop事件 当一个条目(即允许下降)是掉在目标SurfaceListBox控制,DropEvent事件引发时。事件处理程序添加数据在光标到TargetItems集合,绑定到该控件。

private void OnDropTargetDrop(object sender, SurfaceDragDropEventArgs e)
        {
            TargetItems.Add(e.Cursor.Data as DataItem);
        }

(12)DragCompleted事件当目标Item移动到被放置的Listbox中删除原目标元素的Item元素项

 
private void OnDragCompleted(object sender, SurfaceDragCompletedEventArgs e)
        {
            // If the operation is Move, remove the data from drag source.
            if (e.Cursor.Effects == DragDropEffects.Move)
            {
                SourceItems.Remove(e.Cursor.Data as DataItem);
            }
        }

 

参考链接:http://msdn.microsoft.com/en-us/library/ff727837.aspx

posted on 2013-02-18 13:55  winfwu  阅读(1233)  评论(0编辑  收藏  举报