Surface ScatterViewItem拖放块缩放

时间:2014-04-15 11:41:41

标签: c# wpf drag-and-drop scale pixelsense

在我的ScatterView中,我想将项目拖放到SurfaceButton上,以将它们添加到SurfaceListBox中。此时一切正常。

这是我的ScatterView的XAML代码:

<UserControl x:Class="Ctms.Presentation.Views.ResultView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:p="clr-namespace:Ctms.Presentation.Properties"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:waf="http://waf.codeplex.com/schemas"
             xmlns:vm="clr-namespace:Ctms.Applications.ViewModels;assembly=Ctms.Applications"
             xmlns:ps="clr-namespace:PieInTheSky;assembly=PieInTheSky"
             xmlns:s="http://schemas.microsoft.com/surface/2008"
             xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
             xmlns:blakenui="clr-namespace:Blake.NUI.WPF.Gestures;assembly=Blake.NUI.WPF"
             IsEnabled="{Binding IsEnabled}"
             waf:ValidationHelper.IsValid="{Binding IsValid, Mode=OneWayToSource}">


    <Grid>
        <s:ScatterView Name="MainScatterView" ItemsSource="{Binding Results}" ItemTemplate="{StaticResource ScatterViewItemDataTemplate}"
                   s:SurfaceDragDrop.DragCanceled="Results_OnDragCanceled"
                   s:SurfaceDragDrop.DragCompleted="Results_OnDragCompleted"
                   blakenui:Events.DoubleTapGesture="Results_DoubleTapGesture"
                   PreviewTouchDown="Results_PreviewTouchDown">
        </s:ScatterView>
    </Grid>
</UserControl>

这是我的DragStart处理程序

private void Results_PreviewTouchDown(object sender, TouchEventArgs e)
{
    FrameworkElement findSource = e.OriginalSource as FrameworkElement;
    ScatterViewItem draggedElement = null;

    // Find the ScatterViewItem object that is being touched.
    while (draggedElement == null && findSource != null)
    {
        if ((draggedElement = findSource as ScatterViewItem) == null)
        {
            findSource = VisualTreeHelper.GetParent(findSource) as FrameworkElement;
        }
    }

    if (draggedElement == null)
    {
        return;
    }

    ResultDataModel data = draggedElement.Content as ResultDataModel;

    // Set the dragged element. This is needed in case the drag operation is canceled.
    data.DraggedElement = draggedElement;

    // Create the cursor visual.
    ContentControl cursorVisual = new ContentControl()
    {
        Content = draggedElement.DataContext,
        Style = FindResource("ResultCursorStyle") as Style
    };

    // Create a list of input devices, 
    // and add the device passed to this event handler.
    List<InputDevice> devices = new List<InputDevice>();
    devices.Add(e.TouchDevice);

    // If there are touch devices captured within the element,
    // add them to the list of input devices.
    foreach (InputDevice device in draggedElement.TouchesCapturedWithin)
    {
        if (device != e.TouchDevice)
        {
            devices.Add(device);
        }
    }

    // Get the drag source object.
    ItemsControl dragSource = ItemsControl.ItemsControlFromItemContainer(draggedElement);

    // Start the drag-and-drop operation.
    SurfaceDragCursor cursor =
        SurfaceDragDrop.BeginDragDrop(
        // The ScatterView object that the cursor is dragged out from.
          dragSource,
        // The ScatterViewItem object that is dragged from the drag source.
          draggedElement,
        // The visual element of the cursor.
          cursorVisual,
        // The data attached with the cursor.
          draggedElement.DataContext,
        // The input devices that start dragging the cursor.
          devices,
        // The allowed drag-and-drop effects of the operation.
          DragDropEffects.Copy);

    e.Handled = (cursor != null);
}

在放置ScatterViewItem-Template的ResourceDictionary中,我还添加了一个SizeChanged-Listener:

private void ResultWrapper_SizeChanged(object sender, SizeChangedEventArgs e)
{
    FrameworkElement scatterViewItem = e.Source as FrameworkElement;
    ResultDataModel result = scatterViewItem.DataContext as ResultDataModel;

    //do some stuff when scaling
}

现在,当我禁用DragStart-Handler时,我的SizeChanged-Handler会被调用。但是如果我启用DragStart-Handler,我就无法调整ScatterViewItem的大小,导致立即调用DragStart。

有什么解决方案我可以捕捉这两个事件,拖放和缩放吗?

1 个答案:

答案 0 :(得分:1)

好的,那很简单。使用ScatterViewItem.ContainerDeactivated事件。当IsContainerActive切换为false时(当不再操作容器时)将触发。现在你所要做的就是测试是否超过了你的一个按钮。使用ActualCenter属性知道SVI的放置位置。

编辑:以下是一些代码

我设置了一个非常简单的窗口:

<Grid>
    <Canvas>
        <Button x:Name="btnButton1" Canvas.Left="100" Canvas.Top="200" Width="200" Height="200">Button 1</Button>
        <Button x:Name="btnButton2" Canvas.Left="500" Canvas.Top="300" Width="200" Height="200">Button 2</Button>
    </Canvas>

    <s:ScatterView x:Name="containerScatterView" s:ScatterViewItem.ContainerDeactivated="ScatterView_ContainerDeactivated">

        <s:ScatterViewItem>
            <Rectangle Fill="Red" Width="100" Height="100"/>
        </s:ScatterViewItem>

        <s:ScatterViewItem>
            <Rectangle Fill="Green" Width="100" Height="100"/>
        </s:ScatterViewItem>

    </s:ScatterView>
</Grid>

现在是事件处理程序的代码:

private void ScatterView_ContainerDeactivated(object sender, RoutedEventArgs e)
{
    ScatterViewItem sourceSVI =  (ScatterViewItem)e.OriginalSource;

    //Retrieve Button1 size
    Rect btn1Bounds = VisualTreeHelper.GetDescendantBounds(btnButton1);
    //Get the transform between SV and the button1. We need it because ActualCenter is relative to SV.
    GeneralTransform transform1 = containerScatterView.TransformToVisual(btnButton1);

    if (btn1Bounds.Contains(transform1.Transform(sourceSVI.ActualCenter)))
    {
        //If ActualPoint is in bounds of the button1 then do something
        Console.WriteLine("Dropped on Button 1");
    }

    //Retrieve Button2 size
    Rect btn2Bounds = VisualTreeHelper.GetDescendantBounds(btnButton2);
    //Get the transform between SV and the button1. We need it because ActualCenter is relative to SV.
    GeneralTransform transform2 = containerScatterView.TransformToVisual(btnButton2);

    if (btn2Bounds.Contains(transform2.Transform(sourceSVI.ActualCenter)))
    {
        //If ActualPoint is in bounds of the button2 then do something else
        Console.WriteLine("Dropped on Button 2");
    }
}

我在这里用最简单的方法测试点是否在按钮上。我只是测试点是否在按钮的边界矩形内。也可以使用WPF HitTesting。