Deepak
Deepak

Reputation: 575

How to drag and drop rows in NSTableView in Mac

I have struck with one point i.e now I have got a list of data using NSTableView but what my requirement is, able to drag and drop that rows from one row position to another row position. please give any suggestion for get out this problem. Thanks in advance.enter image description here

My sample code

Upvotes: 1

Views: 251

Answers (1)

SushiHangover
SushiHangover

Reputation: 74209

Within your NSTableViewDataSource subclass implement WriteRows, ValidateDrop and AcceptDrop and register which Drag/Drop targets your NSTableView accepts. In this case you are only accepting Drops from within your own NSTableView.

Assign a name that will be used for valid drag operations on this NSTableView:

// Any name can be registered, I find using the class name 
// of the items in the datasource is cleaner than a const string
string DragDropType = typeof(Product).FullName;

Register the drag types for your NSTableView:

ProductTable.RegisterForDraggedTypes(new string[] { DragDropType }); 

Implement drag/drop methods on your NSTableViewDataSource:

public override bool WriteRows(NSTableView tableView, NSIndexSet rowIndexes, NSPasteboard pboard)
{
    var data = NSKeyedArchiver.ArchivedDataWithRootObject(rowIndexes);
    pboard.DeclareTypes(new string[] { DragDropType }, this);
    pboard.SetDataForType(data, DragDropType);
    return true;
}

public override NSDragOperation ValidateDrop(NSTableView tableView, NSDraggingInfo info, nint row, NSTableViewDropOperation dropOperation)
{
    tableView.SetDropRowDropOperation(row, dropOperation);
    return NSDragOperation.Move;
}

public override bool AcceptDrop(NSTableView tableView, NSDraggingInfo info, nint row, NSTableViewDropOperation dropOperation)
{
    var rowData = info.DraggingPasteboard.GetDataForType(DragDropType);
    if (rowData == null)
        return false;
    var dataArray = NSKeyedUnarchiver.UnarchiveObject(rowData) as NSIndexSet;
    Console.WriteLine($"{dataArray}");
    // Move hack for this example... you need to handle the complete NSIndexSet
    tableView.BeginUpdates();
    var tmpProduct = Products[(int)dataArray.FirstIndex];
    Products.RemoveAt((int)dataArray.FirstIndex);
    if (Products.Count == row - 1)
        Products.Insert((int)row - 1 , tmpProduct);
    else 
        Products.Insert((int)row, tmpProduct);
    tableView.ReloadData();
    tableView.EndUpdates();
    return true;
}

Upvotes: 2

Related Questions