Drag and Drop in UWP and iOS (Xamarin Forms)

rughvi8784rughvi8784 GBMember ✭✭
edited July 2018 in Xamarin.Forms

Let's say we have a set of positions and we have to drag filled position and drop into empty position.
In UWP render the custom control and

  1. add private field

    private DragDropGestureHandler dragAndDropHandler = new DragDropGestureHandler();
    
  2. in OnElementPropertyChanged function

    protected override void OnElementChanged(ElementChangedEventArgs<PositionCustomView> e)
    {
    
        base.OnElementChanged(e);
    
        if (e.OldElement == null)
        {
            this.CanDrag = true;
            this.AllowDrop = true;
            this.DragOver += dragAndDropHandler.PositionCustomViewRenderer_DragOver;
            this.DragStarting += dragAndDropHandler.PositionCustomViewRenderer_DragStarting;
            this.Drop += dragAndDropHandler.PositionCustomViewRenderer_Drop;
        }
    
        if (e.NewElement == null)
        {
            this.CanDrag = false;
            this.AllowDrop = false;
            this.DragOver -= dragAndDropHandler.PositionCustomViewRenderer_DragOver;
            this.DragStarting -= dragAndDropHandler.PositionCustomViewRenderer_DragStarting;
            this.Drop -= dragAndDropHandler.PositionCustomViewRenderer_Drop;
        }
    }
    
  3. DragDropGestureHandler

    public class DragDropGestureHandler
    
    {        
        public void PositionCustomViewRenderer_DragStarting(UIElement sender, DragStartingEventArgs args)
        {
            var viewRenderer = sender as PositionCustomViewRenderer;
            var element = viewRenderer?.Element;
            if (element.AllowMove)
            {
                args.Cancel = false;
                args.Data.Properties.Add("customView", (element));
                element.PositionMovingCommand?.Execute(element.Position);
            }
            else
            {
                args.Cancel = true;
            }
        }
    
    public async void PositionCustomViewRenderer_Drop(object sender, DragEventArgs e)
    {
        var viewRenderer = sender as PositionCustomViewRenderer;
        var element = viewRenderer?.Element;
        var result = e.DataView?.Properties?.
                    SingleOrDefault(p => p.Key == "customView" && p.Value.GetType() == typeof(PositionCustomView));
        var positionCustomView = result?.Value as PositionCustomView;
    
        element.PositionMovedCommand?.Execute(new Tuple<int, int?, int>(PositionCustomView.Position, PositionCustomView.SessionId, element.Position));
    }        
    
    public void PositionCustomViewRenderer_DragOver(object sender, DragEventArgs e)
    {
        var viewRenderer = sender as PositionCustomViewRenderer;
        var element = viewRenderer?.Element;
        if (element.AllowDrop)
        {
            e.AcceptedOperation = DataPackageOperation.Copy | DataPackageOperation.Move;
        }
        else
        {
            e.AcceptedOperation = DataPackageOperation.None;
        }
    }
    
    }
    

In iOS render the custom control and

1.add private fields

private UIDragInteraction dragInteraction = null;
    private UIDropInteraction dropInteraction = null;
    private DragDropGestureHandler dragDropGestureHandler = new DragDropGestureHandler();
  1. in OnElementPropertyChanged function

    protected override void OnElementChanged(ElementChangedEventArgs<View> e)
    {
        base.OnElementChanged(e);
        dragInteraction = new UIDragInteraction(dragDropGestureHandler);
        dropInteraction = new UIDropInteraction(dragDropGestureHandler);
    
    
        if (e.OldElement == null)
        {
            this.UserInteractionEnabled = true;
            this.AddInteraction(dragInteraction);
            this.AddInteraction(dropInteraction);
        }
        if(e.NewElement == null)
        {
            this.RemoveInteraction(dragInteraction);
            this.RemoveInteraction(dropInteraction);
        }
    
    }
    
  2. DragDropGestureHandler

    public class DragDropGestureHandler : NSObject, IUIDragInteractionDelegate, IUIDropInteractionDelegate
    {
    
    public UIDragItem[] GetItemsForBeginningSession(UIDragInteraction interaction, IUIDragSession session)
    {
        var viewRenderer = interaction.View as PositionCustomViewRenderer;
        var view = viewRenderer.Element as PositionCustomView;
        if (view.AllowMove)
        {
            view.PositionMovingCommand?.Execute(view.Position);
            var provider = new NSItemProvider(new NSString($"{view?.Position}:{view?.SessionId}"));
            var item = new UIDragItem(provider);
            return new UIDragItem[] { item };
        }
        else
        {
            return null;
        }
    }
    [Export("dropInteraction:sessionDidUpdate:")]
    public UIDropProposal SessionDidUpdate(UIDropInteraction interaction, IUIDropSession session)
    {
        var viewRenderer = interaction.View as PositionCustomViewRenderer;
        var view = viewRenderer.Element as PositionCustomView;
        UIDropProposal proposal = new UIDropProposal(UIDropOperation.Copy);
        if (view.AllowDrop)
        {
            proposal = new UIDropProposal(UIDropOperation.Copy);
        }
        else
        {
            proposal = new UIDropProposal(UIDropOperation.Forbidden);
        }
        return proposal;
    }
    
    
    [Export("dropInteraction:performDrop:")]
    public void PerformDrop(UIDropInteraction interaction, IUIDropSession session)
    {
        var viewRenderer = interaction.View as PositionCustomViewRenderer;
        var view = viewRenderer.Element as PositionCustomView;
        session.LoadObjects<NSString>(strings =>
        {
            string string0 = strings[0];
    
            string[] positionSessionIds = string0.Split(':');
            var position = int.Parse(positionSessionIds[0]);
            int? sessionId = (positionSessionIds[1] == null) ? default(int?) : int.Parse(positionSessionIds[1]);
    
            view.PositionMovedCommand?.Execute(new Tuple<int, int?, int>(position, sessionId, view.Position));
        });
    }
    
    }
    

Posts

  • robbitrobbit CNMember Xamurai

    Hi @rughvi8784

    Do you want to achieve it on Android platform?

  • SzbestaSzbesta Member ✭✭✭
    edited July 2018

    I dont think so as he/she stated UWP and iOS in the title

  • rughvi8784rughvi8784 GBMember ✭✭

    @robbit thanks and I am fine for now with iOS and UWP. I am sure there should be something similar in Android as well.

Sign In or Register to comment.