I'm trying to implement a photo sharing application with two Android phones and a surface application using the toolkit for Windows Touch Beta. Therefore, I created a ScatterView
called MainScatterView
as basic Layout. Each time a user touches the screen, a Blob will be created in this MainScatterView
. The Blob itself is a ScatterViewItem
that contains a ScatterView
named Blob
. This Blob
contains the photos of a specific album on the Android phone.
Dragging & Dropping photos between two blobs works well, but if I want to drop an item on the MainScatterView
the dependant onDrop
method is never called. My assumption is that this problem depends on the different Layers that a Blob
ScatterView
and the MainScatterView
have, but that's only an assumption. Here's my XAML code:
<s:SurfaceWindow
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"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="FotoSharing.SurfaceWindow1"
Width="1920" Height="1080" BorderThickness="5" BorderBrush="White" WindowStyle="None">
<s:SurfaceWindow.Resources>
<ImageBrush x:Key="WindowBackground" Stretch="None" Opacity="0.6" ImageSource="pack://application:,,,/Resources/WindowBackground.jpg"/>
</s:SurfaceWindow.Resources>
<s:SurfaceWindow.Background>
<LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
<GradientStop Color="Black"/>
<GradientStop Color="#FFA784C8" Offset="1"/>
</LinearGradientBrush>
</s:SurfaceWindow.Background>
<s:ScatterView x:Name="MainScatterView" Margin="0" Width="1920" Height="1080" AllowDrop="True" s:SurfaceDragDrop.Drop="OnDrop" PreviewTouchDown="OnDragSourcePreviewTouchDown">
<s:ScatterViewItem x:Name="sviBlob1" Width="600" Height="600" Orientation="0" CanMove="False" CanRotate="False" CanScale="False" Visibility="Collapsed">
<Viewbox x:Name="ViewBoxBlob1">
<s:ScatterView x:Name="Blob1" Width="600" Height="600" AllowDrop="True" s:SurfaceDragDrop.Drop="OnDrop" PreviewTouchDown="OnDragSourcePreviewTouchDown">
<s:ScatterView.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="#FFA784C8" Offset="1"/>
</LinearGradientBrush>
</s:ScatterView.Background>
<s:ScatterViewItem x:Name="sviBlob1Header" Width="600" Height="40" CanRotate="False" CanMove="False" CanScale="False" Orientation="0" Center="300,20" HorizontalContentAlignment="Center" VerticalContentAlignment="Center">
<s:ScatterViewItem.Background>
<LinearGradientBrush EndPoint="0,0" StartPoint="0,1">
<GradientStop Color="#FFA4B4BD" Offset="0"/>
<GradientStop Color="#FF65438F" Offset="1"/>
</LinearGradientBrush>
</s:ScatterViewItem.Background>
<Canvas x:Name="Blob1Header" Height="40" Width="600">
<Image x:Name="Blob1NavigateLeft" Height="40" Width="50" Source="Icons\navigate_left_256.png" Canvas.Left="480" TouchDown="handleTouchDownNavigateLeft" Visibility="Hidden"/>
<Image x:Name="Blob1NavigateRight" Height="40" Width="50" Source="Icons\navigate_right_256.png" Canvas.Left="535" TouchDown="handleTouchDownNavigateRight" Visibility="Hidden"/>
<Image x:Name="Blob1ZoomIn" Height="40" Width="50" Source="Icons\zoom_in_128.png" Canvas.Left="294" TouchDown="handleTouchDownZoomIn"/>
<Image x:Name="Blob1ZoomOut" Height="40" Width="50" Source="Icons\zoom_out_128.png" Canvas.Left="360" TouchDown="handleTouchDownZoomOut"/>
<Image x:Name="Blob1Pin" Height="50" Width="50" Source="Icons\pin_black_128.png" Canvas.Left="480" TouchDown="handleTouchDownPin"/>
<Image x:Name="Blob1DragDrop" Height="40" Width="46" Source="Icons\dragdrop.png" Canvas.Left="430" TouchDown="handleTouchDownDragDrop"/>
<Image x:Name="Blob1Close" Height="40" Width="50" Source="Icons\delete_blob_128.png" Canvas.Left="535" TouchDown="handleTouchDownClose"/>
<Image x:Name="Blob1Album" Height="40" Width="50" Source="Icons\album_128.png"/>
<Label x:Name="Blob1AlbumName" Content="Label" Width="250" Height="40" Canvas.Left="52" FontSize="26.667" Canvas.Top="-4" FontWeight="Bold" FontStyle="Italic"/>
</Canvas></s:ScatterViewItem>
</s:ScatterView>
</Viewbox>
</s:ScatterViewItem>
<s:ScatterViewItem x:Name="sviBlob2" Width="600" Height="600" Orientation="0" CanMove="False" CanRotate="False" CanScale="False" Visibility="Collapsed">
<Viewbox x:Name="ViewBoxBlob2">
<s:ScatterView x:Name="Blob2" Width="600" Height="600" AllowDrop="True" s:SurfaceDragDrop.Drop="OnDrop" PreviewTouchDown="OnDragSourcePreviewTouchDown">
<s:ScatterView.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="#FFA784C8" Offset="1"/>
</LinearGradientBrush>
</s:ScatterView.Background>
<s:ScatterViewItem x:Name="sviBlob2Header" Width="600" Height="40" CanRotate="False" CanMove="False" CanScale="False" Orientation="0" Center="300,20" HorizontalContentAlignment="Center" VerticalContentAlignment="Center">
<s:ScatterViewItem.Background>
<LinearGradientBrush EndPoint="0,0" StartPoint="0,1">
<GradientStop Color="#FFA4B4BD" Offset="0"/>
<GradientStop Color="#FF65438F" Offset="1"/>
</LinearGradientBrush>
</s:ScatterViewItem.Background>
<Canvas x:Name="Blob2Header" Height="40" Width="600">
<Image x:Name="Blob2NavigateLeft" Height="40" Width="50" Source="Icons\navigate_left_256.png" Canvas.Left="480" TouchDown="handleTouchDownNavigateLeft" Visibility="Hidden"/>
<Image x:Name="Blob2NavigateRight" Height="40" Width="50" Source="Icons\navigate_right_256.png" Canvas.Left="535" TouchDown="handleTouchDownNavigateRight" Visibility="Hidden"/>
<Image x:Name="Blob2ZoomIn" Height="40" Width="50" Source="Icons\zoom_in_128.png" Canvas.Left="294" TouchDown="handleTouchDownZoomIn"/>
<Image x:Name="Blob2ZoomOut" Height="40" Width="50" Source="Icons\zoom_out_128.png" Canvas.Left="360" TouchDown="handleTouchDownZoomOut"/>
<Image x:Name="Blob2Pin" Height="50" Width="50" Source="Icons\pin_black_128.png" Canvas.Left="480" TouchDown="handleTouchDownPin"/>
<Image x:Name="Blob2DragDrop" Height="40" Width="46" Source="Icons\dragdrop.png" Canvas.Left="430" TouchDown="handleTouchDownDragDrop"/>
<Image x:Name="Blob2Close" Height="40" Width="50" Source="Icons\delete_blob_128.png" Canvas.Left="535" TouchDown="handleTouchDownClose"/>
<Image x:Name="Blob2Album" Height="40" Width="50" Source="Icons\album_128.png"/>
<Label x:Name="Blob2AlbumName" Content="Label" Width="250" Height="40" Canvas.Left="52" FontSize="26.667" Canvas.Top="-4" FontWeight="Bold" FontStyle="Italic"/>
</Canvas></s:ScatterViewItem>
</s:ScatterView>
</Viewbox>
</s:ScatterViewItem>
</s:ScatterView>
The two depending Methods onDrop and OnDragPreviewTouchDown look like this:
private void OnDragSourcePreviewTouchDown(object sender, TouchEventArgs e)
{
if (allowDragDrop == true)
{
if (e.OriginalSource is Image)
{
if ((e.OriginalSource as Image).Parent is ScatterViewItem) // prevent that image of Hederline is handled as foto
{
Image foto = (Image)e.OriginalSource;
string fotoID = (string)foto.DataContext;
ScatterViewItem draggedElement = (ScatterViewItem)(e.OriginalSource as Image).Parent;
double width = draggedElement.ActualWidth;
double height = draggedElement.ActualHeight;
double orientation = draggedElement.ActualOrientation;
ScatterViewItemDataContext context = (ScatterViewItemDataContext)draggedElement.DataContext;
context.originCenter = draggedElement.ActualCenter;
ScatterView dragSource = (ScatterView)draggedElement.Parent;
ScatterViewItem clonedDraggedElement = createScatterViewItemClone(width, height, orientation, context, fotoID);
// Create the cursor visual.
ContentControl cursorVisual = new ContentControl()
{
Content = clonedDraggedElement
};
// 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);
}
}
SurfaceDragCursor startDragOkay =
SurfaceDragDrop.BeginDragDrop(
dragSource, // The ScatterView object that the cursor is dragged out from.
draggedElement, // The ScatterViewItem object that is dragged from the drag source.
cursorVisual, // The visual element of the cursor.
draggedElement, // The data attached with the cursor.
devices, // The input devices that start dragging the cursor.
System.Windows.DragDropEffects.Move); // The allowed drag-and-drop effects of the operation.
// This if-clause causes, that the scatterviewitems are not deleted on the dragsource!
if (startDragOkay != null)
{
// Set e.Handled to true, otherwise the ScatterViewItem will capture the touch
// and cause the BeginDragDrop to fail.
e.Handled = true;
// Hide the ScatterViewItem.
draggedElement.Visibility = Visibility.Hidden;
}
}
}
}
}
private void OnDrop(object sender, SurfaceDragDropEventArgs e)
{
e.Handled = false;
Console.WriteLine(sender.ToString());
if (sender is ScatterView)
{
// Get drag source SV and drop SV
ScatterView dropScatterView = sender as ScatterView;
ScatterView dragSource = (ScatterView)e.Cursor.DragSource;
// Receive dragged Element from Cursor
ScatterViewItem draggedElement = (ScatterViewItem)e.Cursor.Data;
Image foto = (Image)draggedElement.Content;
// Get informations to clone dragged item
string fotoID = (string)foto.DataContext;
double width = draggedElement.ActualWidth;
double height = draggedElement.ActualHeight;
double orientation = draggedElement.ActualOrientation;
ScatterViewItemDataContext context = (ScatterViewItemDataContext)draggedElement.DataContext;
// Clone dragged item
ScatterViewItem clonedDraggedElement = createScatterViewItemClone(width, height, orientation, context, fotoID);
clonedDraggedElement.Center = e.Cursor.GetPosition(dropScatterView);
// Remove Item from Drag-Source
dragSource.Items.Remove(draggedElement);
// Item was droppeded in the same Blob
if (dragSource.Equals(dropScatterView))
{
dropScatterView.Items.Add(clonedDraggedElement);
// Update Center of Blob with Animation
PointAnimation pa = new PointAnimation();
pa.From = e.Cursor.GetPosition(dropScatterView);
pa.To = context.originCenter;
pa.Duration = TimeSpan.FromMilliseconds(500);
pa.FillBehavior = FillBehavior.HoldEnd;
clonedDraggedElement.BeginAnimation(ScatterViewItem.CenterProperty, pa);
}
else if (dropScatterView.Equals(MainScatterView) == false) // Foto was dropped to another Blob!
{
BlobInfo blobInfoDropSV = (BlobInfo)dropScatterView.DataContext;
// Add new fotoID to array of fotoIDs
blobInfoDropSV.fotoIDs.Add(fotoID);
// Add dragged foto to grid of Blob
FotoSampler fotoSampler = new FotoSampler();
Image dropFoto = fotoSampler.getImageByFotoID(fotoID);
ScatterViewItem sviToDrop = calculateFotoInGridPosition(blobInfoDropSV.fotoIDs.Count-1, dropFoto);
dropScatterView.Items.Add(sviToDrop);
PointAnimation pa = new PointAnimation();
pa.From = e.Cursor.GetPosition(dropScatterView);
pa.To = sviToDrop.Center;
pa.Duration = TimeSpan.FromMilliseconds(500);
pa.FillBehavior = FillBehavior.Stop;
sviToDrop.BeginAnimation(ScatterViewItem.CenterProperty, pa);
// refresh drag-Blob
BlobInfo blobInfoDragSV = (BlobInfo)dragSource.DataContext;
removeFotosFromBlob(dragSource);
int nbrOfFotosBeforeRefresh = blobInfoDragSV.fotoIDs.Count;
int idOfFotoToDelete = 0;
for (int i = 0; i < nbrOfFotosBeforeRefresh; i++) // remove FotoID from List of FotoIDs
{
if (blobInfoDragSV.fotoIDs[i].Equals(fotoID) == true)
{
idOfFotoToDelete = i;
}
}
blobInfoDragSV.fotoIDs.RemoveAt(idOfFotoToDelete); // delete draggedElement
createFotosInBlob(blobInfoDragSV.blobNbr, blobInfoDragSV.fotoIDs, blobInfoDragSV.zoomLevel); // calculate and order fotos again
// send Message mit Item to User
TcpClient client = new TcpClient(blobInfoDropSV.user.ip);
client.sendeNachricht("01#"+fotoID+"#");
}
}
}
I really tried a lot to solve this problem but nothing results in a comfortable solution.
I've recognized, that the ScatterView-Property Background
has to be defined. Only if this property is set, events like the SurfaceDragDropEventArgs
can be catched. Crazy!