在我的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。
有什么解决方案我可以捕捉这两个事件,拖放和缩放吗?
答案 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。