Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,18 @@ void ClearContainerEventHandlers()
_container.ManipulationCompleted -= OnManipulationCompleted;
_container.PointerCanceled -= OnPointerCanceled;
}

if (Element is View && ElementGestureRecognizers is { } gestureRecognizers)
{
if (gestureRecognizers.FirstGestureOrDefault<DragGestureRecognizer>() is { } dragGesture)
{
dragGesture.PropertyChanged -= HandleDragAndDropGesturePropertyChanged;
}
if (gestureRecognizers.FirstGestureOrDefault<DropGestureRecognizer>() is { } dropGesture)
{
dropGesture.PropertyChanged -= HandleDragAndDropGesturePropertyChanged;
}
}
}
}

Expand Down Expand Up @@ -822,26 +834,36 @@ void UpdateDragAndDropGestureRecognizers()
return;
}

bool canDrag = gestures.FirstGestureOrDefault<DragGestureRecognizer>()?.CanDrag ?? false;
bool allowDrop = gestures.FirstGestureOrDefault<DropGestureRecognizer>()?.AllowDrop ?? false;
DragGestureRecognizer? dragGesture = gestures.FirstGestureOrDefault<DragGestureRecognizer>();
DropGestureRecognizer? dropGesture = gestures.FirstGestureOrDefault<DropGestureRecognizer>();

if (canDrag)
if (dragGesture is not null)
{
_subscriptionFlags |= SubscriptionFlags.ContainerDragEventsSubscribed;
dragGesture.PropertyChanged -= HandleDragAndDropGesturePropertyChanged;
dragGesture.PropertyChanged += HandleDragAndDropGesturePropertyChanged;

_container.CanDrag = true;
_container.DragStarting += HandleDragStarting;
_container.DropCompleted += HandleDropCompleted;
if (dragGesture.CanDrag && ((_subscriptionFlags & SubscriptionFlags.ContainerDragEventsSubscribed) == 0))
{
_subscriptionFlags |= SubscriptionFlags.ContainerDragEventsSubscribed;
_container.CanDrag = true;
_container.DragStarting += HandleDragStarting;
_container.DropCompleted += HandleDropCompleted;
}
}

if (allowDrop)
if (dropGesture is not null)
{
_subscriptionFlags |= SubscriptionFlags.ContainerDropEventsSubscribed;
dropGesture.PropertyChanged -= HandleDragAndDropGesturePropertyChanged;
dropGesture.PropertyChanged += HandleDragAndDropGesturePropertyChanged;

_container.AllowDrop = true;
_container.DragOver += HandleDragOver;
_container.Drop += HandleDrop;
_container.DragLeave += HandleDragLeave;
if (dropGesture.AllowDrop && ((_subscriptionFlags & SubscriptionFlags.ContainerDropEventsSubscribed) == 0))
{
_subscriptionFlags |= SubscriptionFlags.ContainerDropEventsSubscribed;
_container.AllowDrop = true;
_container.DragOver += HandleDragOver;
_container.Drop += HandleDrop;
_container.DragLeave += HandleDragLeave;
}
}
}

Expand Down Expand Up @@ -983,6 +1005,15 @@ void HandleDoubleTapped(object sender, DoubleTappedRoutedEventArgs doubleTappedR
doubleTappedRoutedEventArgs.Handled = true;
}

void HandleDragAndDropGesturePropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == DragGestureRecognizer.CanDragProperty.PropertyName ||
e.PropertyName == DropGestureRecognizer.AllowDropProperty.PropertyName)
{
UpdateDragAndDropGestureRecognizers();
}
}

DragEventArgs ToDragEventArgs(UI.Xaml.DragEventArgs e, PlatformDragEventArgs platformArgs)
{
// The package should never be null here since the UI.Xaml.DragEventArgs have already been initialized
Expand Down
61 changes: 61 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue12726.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
namespace Maui.Controls.Sample.Issues
{

[Issue(IssueTracker.Github, 12726, "Drag and Drop Gesture Fails on Runtime Changes of CanDrag and AllowDrop in Windows",
PlatformAffected.UWP)]
public class Issue12726 : TestContentPage
{
protected override void Init()
{
Label dragResult = new Label();
Label dropResult = new Label();

DragGestureRecognizer dragGestureRecognizer = new DragGestureRecognizer { CanDrag = false };
Label dragBox = new Label
{
HeightRequest = 200,
WidthRequest = 200,
BackgroundColor = Colors.Purple,
GestureRecognizers = { dragGestureRecognizer },
AutomationId = "DragElement"
};
dragGestureRecognizer.DragStarting += (_, __) => dragResult.Text = "DragEventTriggered";

DropGestureRecognizer dropGestureRecognizer = new DropGestureRecognizer { AllowDrop = false };
Label dropBox = new Label
{
HeightRequest = 200,
WidthRequest = 200,
BackgroundColor = Colors.Pink,
GestureRecognizers = { dropGestureRecognizer },
AutomationId = "DropTarget"
};
dropGestureRecognizer.Drop += (_, __) => dropResult.Text = "DropEventTriggered";

Button button = new Button
{
Text = "Enable Drag and Drop",
AutomationId = "EnableDragAndDrop"
};

button.Clicked += (_, __) =>
{
dragGestureRecognizer.CanDrag = true;
dropGestureRecognizer.AllowDrop = true;
};

Content = new StackLayout
{
Spacing = 5,
Children =
{
dragBox,
dropBox,
button,
dragResult,
dropResult
}
};
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;

namespace Microsoft.Maui.TestCases.Tests.Issues
{
public class Issue12726 : _IssuesUITest
{
public Issue12726(TestDevice testDevice) : base(testDevice)
{
}

public override string Issue => "Drag and Drop Gesture Fails on Runtime Changes of CanDrag and AllowDrop in Windows";

[Test]
[Category(UITestCategories.DragAndDrop)]
public void DragAndDropShouldWorkRunTime()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is failing on Windows:

at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2352
   at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2367
   at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 663
   at Microsoft.Maui.TestCases.Tests.Issues.Issue12726.DragAndDropShouldWorkRunTime() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue12726.cs:line 23
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jsuarezruiz,

Thank you for pointing this out! The failure appears to be due to the programmatic drop operation not functioning correctly on the Windows platform in the CI environment, despite working on local machines. I have modified the test accordingly, and it should pass in the next CI run.

{
App.WaitForElement("EnableDragAndDrop");
App.Tap("EnableDragAndDrop");
App.DragAndDrop("DragElement", "DropTarget");
App.WaitForElement("DragEventTriggered");
}
}
}
Loading