Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UWP drag and drop custom type/class

Hy there, I'm trying to enable drag & drop between 2 GridViews, I managed to do it with the custom types of the "DataPackage" class (SetText, SetBitmap, etc..) but I can't figure out how to do this with a custom class/type. Both GridViews are data-bound to the same custom class (only a couple of properties, int, string, bitmapimage), I simply would like to drag directly this data items from one GridView to the other. Thank you very much for your help!

like image 920
frenchfaso Avatar asked Mar 14 '23 03:03

frenchfaso


2 Answers

So to summarize for the benefit of others, I added these to event handlers to DataTemplate content, as I only wanted items of a certain (ViewModel) type to be draggable.

    private void Grid_Drop(object sender, DragEventArgs e)
    {
        if (sender is FrameworkElement)
        {
            var fe = sender as FrameworkElement;
            var targetIvm = fe.DataContext as ItemViewModel;
            object obj = null;
            if(e.DataView.Properties.TryGetValue("ItemViewModel", out obj))
            {
                var sourceIvm = obj as ItemViewModel;
                vm.MoveItem(sourceIvm, targetIvm);
            }
        }
    }

    private void Grid_DragStarting(Windows.UI.Xaml.UIElement sender, DragStartingEventArgs args)
    {
        if (sender is FrameworkElement)
        {
            var fe = sender as FrameworkElement;
            var item = new KeyValuePair<string, object>("ItemViewModel", fe.DataContext);
            args.Data.RequestedOperation = DataPackageOperation.Move;
            args.Data.Properties.Add("ItemViewModel", fe.DataContext);
        }
    }
like image 193
Arwin Avatar answered Mar 23 '23 04:03

Arwin


I had the same issue please check this example I used Behaviors because I used MVVM pattern but I did this for ListView but is the same for GridView with small changes.

Change the Behaviors <ListView> to <GridView>

This behavior is attached in the ListView where you want drag the item

public class StartingDragBehavior:Behavior<ListView>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        this.AssociatedObject.CanDragItems = true;
        this.AssociatedObject.DragItemsStarting += AssociatedObject_DragItemsStarting;
    }


    private void AssociatedObject_DragItemsStarting(object sender, DragItemsStartingEventArgs e)
    {
        e.Data.RequestedOperation = Windows.ApplicationModel.DataTransfer.DataPackageOperation.Copy;
        if(e.Items!=null && e.Items.Any())
        {
            e.Data.Properties.Add("item", e.Items.FirstOrDefault());

        }
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        this.AssociatedObject.DragItemsStarting -= AssociatedObject_DragItemsStarting;

    }
}

This behavior is attached in the ListView where you want to drop the item Here another Behavior to catch the drop event.

public class EndDropBehavior : Behavior<ListView>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        this.AssociatedObject.AllowDrop = true;
        this.AssociatedObject.Drop += AssociatedObject_Drop;
        this.AssociatedObject.DragOver += AssociatedObject_DragOver;
    }

    private void AssociatedObject_Drop(object sender, Windows.UI.Xaml.DragEventArgs e)
    {
        if (e.DataView != null &&
            e.DataView.Properties != null &&
            e.DataView.Properties.Any(x => x.Key == "item" && x.Value.GetType() == typeof(MyObject)))
        {
            try
            {
                var def = e.GetDeferral();

                var item = e.Data.Properties.FirstOrDefault(x => x.Key == "item");
                var card = item.Value as MyObject;


                    var list = sender as ListView;
                    var vm = list.DataContext as Infrastructure.ViewModels.CreditCardsViewModel;


                        vm.MyCollection.Add(card);

                def.Complete();
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());

            }

        }
        else
        {
            e.AcceptedOperation = Windows.ApplicationModel.DataTransfer.DataPackageOperation.None;
        }
    }

    private void AssociatedObject_DragOver(object sender, Windows.UI.Xaml.DragEventArgs e)
    {
        if (e.DataView != null &&
            e.DataView.Properties != null &&
            e.DataView.Properties.Any(x => x.Key == "item" && x.Value.GetType() == typeof(MyObject)))
        {

            e.AcceptedOperation = e.AcceptedOperation = Windows.ApplicationModel.DataTransfer.DataPackageOperation.Copy;

        }
        else
        {
            e.AcceptedOperation = Windows.ApplicationModel.DataTransfer.DataPackageOperation.None;
        }
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        this.AssociatedObject.Drop -= AssociatedObject_Drop;

        this.AssociatedObject.DragOver -= AssociatedObject_DragOver;
    }
}

If you are not using MVVM pattern just check the events of the to Behaviors.

like image 42
RicardoPons Avatar answered Mar 23 '23 03:03

RicardoPons