| File: DragAndDrop\DragGestureRecognizer.cs | Web Access |
| Project: src\src\Controls\src\Core\Controls.Core.csproj (Microsoft.Maui.Controls) |
using System; using System.Windows.Input; using Microsoft.Maui.Graphics; namespace Microsoft.Maui.Controls { /// <summary> /// Provides drag gesture recognition and defines the associated events for dragging and dropping. /// </summary> /// <seealso href="https://learn.microsoft.com/dotnet/maui/fundamentals/gestures/drag-and-drop">Conceptual documentation on recognizing a drag and drop gesture</seealso> public class DragGestureRecognizer : GestureRecognizer { /// <summary>Bindable property for <see cref="CanDrag"/>.</summary> public static readonly BindableProperty CanDragProperty = BindableProperty.Create(nameof(CanDrag), typeof(bool), typeof(DragGestureRecognizer), true); /// <summary>Bindable property for <see cref="DropCompletedCommand"/>.</summary> public static readonly BindableProperty DropCompletedCommandProperty = BindableProperty.Create(nameof(DropCompletedCommand), typeof(ICommand), typeof(DragGestureRecognizer), null); /// <summary>Bindable property for <see cref="DropCompletedCommandParameter"/>.</summary> public static readonly BindableProperty DropCompletedCommandParameterProperty = BindableProperty.Create(nameof(DropCompletedCommandParameter), typeof(object), typeof(DragGestureRecognizer), null); /// <summary>Bindable property for <see cref="DragStartingCommand"/>.</summary> public static readonly BindableProperty DragStartingCommandProperty = BindableProperty.Create(nameof(DragStartingCommand), typeof(ICommand), typeof(DragGestureRecognizer), null); /// <summary>Bindable property for <see cref="DragStartingCommandParameter"/>.</summary> public static readonly BindableProperty DragStartingCommandParameterProperty = BindableProperty.Create(nameof(DragStartingCommandParameter), typeof(object), typeof(DragGestureRecognizer), null); bool _isDragActive; /// <summary> /// Initializes a new instance of the <see cref="DragGestureRecognizer"/> class. /// </summary> public DragGestureRecognizer() { } /// <summary> /// Occurs when a drop gesture is completed. /// </summary> public event EventHandler<DropCompletedEventArgs>? DropCompleted; /// <summary> /// Occurs when a drag gesture is detected. /// </summary> public event EventHandler<DragStartingEventArgs>? DragStarting; /// <summary> /// Gets or sets the value which indicates whether the element the gesture recognizer is attached to can be a drag source. /// </summary> /// <remarks>Default value is <see langword="true"/>.</remarks> public bool CanDrag { get { return (bool)GetValue(CanDragProperty); } set { SetValue(CanDragProperty, value); } } /// <summary> /// Gets or sets the command to be executed when a drop gesture is completed. /// </summary> public ICommand DropCompletedCommand { get { return (ICommand)GetValue(DropCompletedCommandProperty); } set { SetValue(DropCompletedCommandProperty, value); } } /// <summary> /// Gets or sets the parameter that's to be passed to the <see cref="DropCompletedCommand"/>. /// </summary> public object DropCompletedCommandParameter { get { return (object)GetValue(DropCompletedCommandParameterProperty); } set { SetValue(DropCompletedCommandParameterProperty, value); } } /// <summary> /// Gets or sets the command to be executed when a drag gesture is first recognized. /// </summary> public ICommand DragStartingCommand { get { return (ICommand)GetValue(DragStartingCommandProperty); } set { SetValue(DragStartingCommandProperty, value); } } /// <summary> /// Gets or sets the parameter that's to be passed to the <see cref="DragStartingCommand"/>. /// </summary> public object DragStartingCommandParameter { get { return (object)GetValue(DragStartingCommandParameterProperty); } set { SetValue(DragStartingCommandParameterProperty, value); } } internal void SendDropCompleted(DropCompletedEventArgs args) { if (!_isDragActive) { // this is mainly relevant for Android // Android fires an Ended action on every single view that has a drop handler // but we only need one of those DropCompleted actions to make it through return; } _isDragActive = false; _ = args ?? throw new ArgumentNullException(nameof(args)); DropCompletedCommand?.Execute(DropCompletedCommandParameter); DropCompleted?.Invoke(this, args); } internal DragStartingEventArgs SendDragStarting(View element, Func<IElement?, Point?>? getPosition = null, PlatformDragStartingEventArgs? platformArgs = null) { var args = new DragStartingEventArgs(getPosition, platformArgs); DragStartingCommand?.Execute(DragStartingCommandParameter); DragStarting?.Invoke(this, args); #pragma warning disable CS0618 // Type or member is obsolete if (!args.Handled) args.Data.PropertiesInternal.Add("DragSource", element); #pragma warning restore CS0618 // Type or member is obsolete #pragma warning disable CS0618 // Type or member is obsolete if (args.Cancel || args.Handled) return args; #pragma warning restore CS0618 // Type or member is obsolete _isDragActive = true; if (args.Data.Image == null && element is IImageElement ie) args.Data.Image = ie.Source; if (String.IsNullOrWhiteSpace(args.Data.Text)) args.Data.Text = element?.GetStringValue(); return args; } } }