diff --git a/Samples/XamlDragAndDrop/cpp/DragAndDropSampleNative.vcxproj b/Samples/XamlDragAndDrop/cpp/DragAndDropSampleNative.vcxproj
index 104df5e012..cb28e36aee 100644
--- a/Samples/XamlDragAndDrop/cpp/DragAndDropSampleNative.vcxproj
+++ b/Samples/XamlDragAndDrop/cpp/DragAndDropSampleNative.vcxproj
@@ -101,10 +101,10 @@
-
- $(VC_IncludePath);$(UniversalCRT_IncludePath);$(WindowsSDK_IncludePath);..\..\..\SharedContent\cpp
-
-
+
+ $(VC_IncludePath);$(UniversalCRT_IncludePath);$(WindowsSDK_IncludePath);..\..\..\SharedContent\cpp
+
+ /bigobj %(AdditionalOptions)4453;28204
@@ -158,6 +158,9 @@
Scenario3_StartDragAsync.xaml
+
+ Scenario4_MoveBetweenListView.xaml
+
@@ -172,6 +175,7 @@
Styles\Styles.xaml
+
@@ -203,6 +207,9 @@
Scenario3_StartDragAsync.xaml
+
+ Scenario4_MoveBetweenListView.xaml
+
diff --git a/Samples/XamlDragAndDrop/cpp/DragAndDropSampleNative.vcxproj.filters b/Samples/XamlDragAndDrop/cpp/DragAndDropSampleNative.vcxproj.filters
index 9c3efd46c9..c99fbe24a7 100644
--- a/Samples/XamlDragAndDrop/cpp/DragAndDropSampleNative.vcxproj.filters
+++ b/Samples/XamlDragAndDrop/cpp/DragAndDropSampleNative.vcxproj.filters
@@ -39,6 +39,7 @@
+
diff --git a/Samples/XamlDragAndDrop/cpp/SampleConfiguration.cpp b/Samples/XamlDragAndDrop/cpp/SampleConfiguration.cpp
index 59ac22360a..8dd04c12df 100644
--- a/Samples/XamlDragAndDrop/cpp/SampleConfiguration.cpp
+++ b/Samples/XamlDragAndDrop/cpp/SampleConfiguration.cpp
@@ -19,5 +19,6 @@ Platform::Array^ MainPage::scenariosInner = ref new Platform::Array
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/XamlDragAndDrop/cpp/Scenario4_MoveBetweenListView.xaml.cpp b/Samples/XamlDragAndDrop/cpp/Scenario4_MoveBetweenListView.xaml.cpp
new file mode 100644
index 0000000000..d5aead4065
--- /dev/null
+++ b/Samples/XamlDragAndDrop/cpp/Scenario4_MoveBetweenListView.xaml.cpp
@@ -0,0 +1,148 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+#include "pch.h"
+#include "Scenario4_MoveBetweenListView.xaml.h"
+
+using namespace concurrency;
+using namespace SDKTemplate;
+using namespace Platform;
+using namespace Platform::Collections;
+using namespace Windows::Foundation;
+using namespace Windows::Foundation::Collections;
+using namespace Windows::UI::Xaml;
+using namespace Windows::UI::Xaml::Controls;
+using namespace Windows::UI::Xaml::Controls::Primitives;
+using namespace Windows::UI::Xaml::Data;
+using namespace Windows::UI::Xaml::Input;
+using namespace Windows::UI::Xaml::Media;
+using namespace Windows::UI::Xaml::Navigation;
+using namespace Windows::ApplicationModel::DataTransfer;
+
+Scenario4_MoveBetweenListView::Scenario4_MoveBetweenListView() : rootPage(MainPage::Current)
+{
+ InitializeComponent();
+
+ _source = GetSampleData();
+ _target = ref new Vector();
+ SourceListView->ItemsSource = _source;
+ TargetListView->ItemsSource = _target;
+}
+
+Vector^ Scenario4_MoveBetweenListView::GetSampleData()
+{
+ return ref new Vector(
+ {
+ ref new String(L"My Research Paper"),
+ ref new String(L"Electricity Bill"),
+ ref new String(L"My To-do list"),
+ ref new String(L"TV sales receipt"),
+ ref new String(L"Water Bill"),
+ ref new String(L"Grocery List"),
+ ref new String(L"Superbowl schedule"),
+ ref new String(L"World Cup E-ticket")
+ });
+}
+
+///
+/// DragItemsStarting is called when the Drag and Drop operation starts
+/// We take advantage of it to set the content of the DataPackage
+/// as well as indicate which operations are supported
+///
+///
+///
+void Scenario4_MoveBetweenListView::ListView_DragItemsStarting(Platform::Object^ sender, Windows::UI::Xaml::Controls::DragItemsStartingEventArgs^ e)
+{
+ // Prepare a string with one dragged item per line
+ // Set the content of the DataPackage
+ if (e->Items->Size > 0)
+ {
+ e->Data->SetText(dynamic_cast(e->Items->GetAt(0)));
+ // As we want our Reference list to say intact, we only allow Move
+ e->Data->RequestedOperation = DataPackageOperation::Move;
+ }
+}
+
+///
+/// DragOver is called when the dragged pointer moves over a UIElement with AllowDrop=True
+/// We need to return an AcceptedOperation != None in either DragOver or DragEnter
+///
+///
+///
+void Scenario4_MoveBetweenListView::ListView_DragOver(Platform::Object^ sender, Windows::UI::Xaml::DragEventArgs^ e)
+{
+ // Our list only accepts text
+ e->AcceptedOperation = (e->DataView->Contains(StandardDataFormats::Text)) ? DataPackageOperation::Move : DataPackageOperation::None;
+}
+
+///
+/// We need to return the effective operation from Drop
+/// This is not important for our source ListView, but it might be if the user
+/// drags text from another source
+///
+///
+///
+void Scenario4_MoveBetweenListView::ListView_Drop(Platform::Object^ sender, Windows::UI::Xaml::DragEventArgs^ e)
+{
+ // This test is in theory not needed as we returned DataPackageOperation.None if
+ // the DataPackage did not contained text. However, it is always better if each
+ // method is robust by itself
+ if (e->DataView->Contains(StandardDataFormats::Text))
+ {
+ // We need to take a Deferral as we won't be able to confirm the end
+ // of the operation synchronously
+ auto def = e->GetDeferral();
+ create_task(e->DataView->GetTextAsync()).then([def, this, sender, e](String^ s)
+ {
+ // Get the lists we need to work with.
+ auto sourceList = (sender->Equals(TargetListView) ? _source : _target);
+ auto targetList = (sender->Equals(TargetListView) ? _target : _source);
+
+ // Remove item from other list
+ unsigned j;
+ if (sourceList->IndexOf(s, &j))
+ {
+ sourceList->RemoveAt(j);
+ }
+
+ // First we need to get the position in the List to drop to
+ auto listview = dynamic_cast(sender);
+ int index = -1;
+
+ // Determine which items in the list our pointer is inbetween.
+ for (int i = 0; i < listview->Items->Size; i++)
+ {
+ auto item = dynamic_cast(listview->ContainerFromIndex(i));
+
+ auto p = e->GetPosition(item);
+
+ if (p.Y - item->ActualHeight < 0)
+ {
+ index = i;
+ break;
+ }
+ }
+
+ if (index < 0)
+ {
+ // We didn't find a transition point, so we're at the end of the list
+ targetList->Append(s);
+ }
+ else if (index < listview->Items->Size)
+ {
+ // Otherwise, insert at the provided index.
+ targetList->InsertAt(index, s);
+ }
+
+ e->AcceptedOperation = DataPackageOperation::Copy;
+ def->Complete();
+ });
+ }
+}
diff --git a/Samples/XamlDragAndDrop/cpp/Scenario4_MoveBetweenListView.xaml.h b/Samples/XamlDragAndDrop/cpp/Scenario4_MoveBetweenListView.xaml.h
new file mode 100644
index 0000000000..265c285edd
--- /dev/null
+++ b/Samples/XamlDragAndDrop/cpp/Scenario4_MoveBetweenListView.xaml.h
@@ -0,0 +1,38 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "Scenario4_MoveBetweenListView.g.h"
+#include "MainPage.xaml.h"
+
+namespace SDKTemplate
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ [Windows::Foundation::Metadata::WebHostHidden]
+ public ref class Scenario4_MoveBetweenListView sealed
+ {
+ public:
+ Scenario4_MoveBetweenListView();
+ private:
+ MainPage^ rootPage;
+
+ Platform::Collections::Vector^ GetSampleData();
+ Platform::Collections::Vector^ _source;
+ Platform::Collections::Vector^ _target;
+
+ void ListView_DragItemsStarting(Platform::Object^ sender, Windows::UI::Xaml::Controls::DragItemsStartingEventArgs^ e);
+ void ListView_DragOver(Platform::Object^ sender, Windows::UI::Xaml::DragEventArgs^ e);
+ void ListView_Drop(Platform::Object^ sender, Windows::UI::Xaml::DragEventArgs^ e);
+ };
+}
diff --git a/Samples/XamlDragAndDrop/cs/DragAndDropSampleManaged.csproj b/Samples/XamlDragAndDrop/cs/DragAndDropSampleManaged.csproj
index 7429c060c4..fa82f12c1f 100644
--- a/Samples/XamlDragAndDrop/cs/DragAndDropSampleManaged.csproj
+++ b/Samples/XamlDragAndDrop/cs/DragAndDropSampleManaged.csproj
@@ -99,6 +99,9 @@
Properties\AssemblyInfo.cs
+
+ Scenario4_MoveBetweenListView.xaml
+ Scenario1_ListView.xaml
@@ -125,6 +128,10 @@
MSBuild:CompileDesigner
+
+ MSBuild:Compile
+ Designer
+ MSBuild:CompileDesigner
diff --git a/Samples/XamlDragAndDrop/cs/SampleConfiguration.cs b/Samples/XamlDragAndDrop/cs/SampleConfiguration.cs
index dcd0fd14fd..d6fc57e4ce 100644
--- a/Samples/XamlDragAndDrop/cs/SampleConfiguration.cs
+++ b/Samples/XamlDragAndDrop/cs/SampleConfiguration.cs
@@ -24,7 +24,8 @@ public partial class MainPage : Page
{
new Scenario() { Title="ListView Drag and Drop and Reorder", ClassType=typeof(Scenario1_ListView)},
new Scenario() { Title="Drag UI Customization", ClassType=typeof(Scenario2_DragUICustomization)},
- new Scenario() { Title="StartDragAsync", ClassType=typeof(Scenario3_StartDragAsync)}
+ new Scenario() { Title="StartDragAsync", ClassType=typeof(Scenario3_StartDragAsync)},
+ new Scenario() { Title="Move Between ListViews", ClassType=typeof(Scenario4_MoveBetweenListView)}
};
}
diff --git a/Samples/XamlDragAndDrop/cs/Scenario4_MoveBetweenListView.xaml b/Samples/XamlDragAndDrop/cs/Scenario4_MoveBetweenListView.xaml
new file mode 100644
index 0000000000..77944496fd
--- /dev/null
+++ b/Samples/XamlDragAndDrop/cs/Scenario4_MoveBetweenListView.xaml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/XamlDragAndDrop/cs/Scenario4_MoveBetweenListView.xaml.cs b/Samples/XamlDragAndDrop/cs/Scenario4_MoveBetweenListView.xaml.cs
new file mode 100644
index 0000000000..70abfbc947
--- /dev/null
+++ b/Samples/XamlDragAndDrop/cs/Scenario4_MoveBetweenListView.xaml.cs
@@ -0,0 +1,151 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+using SDKTemplate;
+using System;
+using System.Collections.ObjectModel;
+using Windows.ApplicationModel.DataTransfer;
+using System.Linq;
+using Windows.Foundation;
+
+namespace DragAndDropSampleManaged
+{
+ ///
+ /// This sample shows how to drag a single item between listviews and maintain the user's desired location.
+ ///
+ public sealed partial class Scenario4_MoveBetweenListView : Page
+ {
+ private MainPage rootPage;
+
+ ObservableCollection _source;
+ ObservableCollection _target;
+
+ public Scenario4_MoveBetweenListView()
+ {
+ this.InitializeComponent();
+
+ _source = GetSampleData();
+ _target = new ObservableCollection();
+ SourceListView.ItemsSource = _source;
+ TargetListView.ItemsSource = _target;
+ }
+ private ObservableCollection GetSampleData()
+ {
+ return new ObservableCollection
+ {
+ "My Research Paper",
+ "Electricity Bill",
+ "My To-do list",
+ "TV sales receipt",
+ "Water Bill",
+ "Grocery List",
+ "Superbowl schedule",
+ "World Cup E-ticket"
+ };
+ }
+
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ rootPage = MainPage.Current;
+ }
+
+ ///
+ /// DragItemsStarting is called when the Drag and Drop operation starts
+ /// We take advantage of it to set the content of the DataPackage
+ /// as well as indicate which operations are supported
+ ///
+ ///
+ ///
+ private void ListView_DragItemsStarting(object sender, DragItemsStartingEventArgs e)
+ {
+ // Prepare a string with one dragged item per line
+ // Set the content of the DataPackage
+ e.Data.SetText(e.Items.FirstOrDefault() as string);
+ // As we want our Reference list to mutate, we only allow Move
+ e.Data.RequestedOperation = DataPackageOperation.Move;
+ }
+
+ ///
+ /// DragOver is called when the dragged pointer moves over a UIElement with AllowDrop=True
+ /// We need to return an AcceptedOperation != None in either DragOver or DragEnter
+ ///
+ ///
+ ///
+ private void ListView_DragOver(object sender, DragEventArgs e)
+ {
+ // Our list only accepts text
+ e.AcceptedOperation = (e.DataView.Contains(StandardDataFormats.Text)) ? DataPackageOperation.Move : DataPackageOperation.None;
+ }
+
+ ///
+ /// We need to return the effective operation from Drop
+ /// This is not important for our source ListView, but it might be if the user
+ /// drags text from another source
+ ///
+ ///
+ ///
+ private async void ListView_Drop(object sender, DragEventArgs e)
+ {
+ // This test is in theory not needed as we returned DataPackageOperation.None if
+ // the DataPackage did not contained text. However, it is always better if each
+ // method is robust by itself
+ if (e.DataView.Contains(StandardDataFormats.Text))
+ {
+ // We need to take a Deferral as we won't be able to confirm the end
+ // of the operation synchronously
+ var def = e.GetDeferral();
+ var text = await e.DataView.GetTextAsync();
+
+ // Get the lists we need to work with.
+ var sourceList = (sender == TargetListView ? _source : _target);
+ var targetList = (sender == TargetListView ? _target : _source);
+
+ // Remove item from other list
+ sourceList.Remove(text);
+
+ // First we need to get the position in the List to drop to
+ var listview = sender as ListView;
+ var index = -1;
+
+ // Determine which items in the list our pointer is inbetween.
+ for (int i = 0; i < listview.Items.Count; i++)
+ {
+ var item = listview.ContainerFromIndex(i) as ListViewItem;
+
+ var p = e.GetPosition(item);
+
+ if (p.Y - item.ActualHeight < 0)
+ {
+ index = i;
+ break;
+ }
+ }
+
+ if (index < 0)
+ {
+ // We didn't find a transition point, so we're at the end of the list
+ targetList.Add(text);
+ }
+ else if (index < listview.Items.Count)
+ {
+ // Otherwise, insert at the provided index.
+ targetList.Insert(index, text);
+ }
+
+ e.AcceptedOperation = DataPackageOperation.Move;
+ def.Complete();
+ }
+ }
+ }
+}