c# drag and drop does not work (BingdingList for DataGridView)

295 views Asked by At

I want to add drag and drop function to my app where Data Grid View is used to display file names. Datasource is a bindinglist. I made another bininglist to store dragged files, and I want to import this binding list to the datasource.

 private void dataGridView1_DragEnter(object sender, DragEventArgs e)
    {
        
        if (e.Data.GetDataPresent(DataFormats.FileDrop))
        {
            e.Effect = DragDropEffects.Copy; 
        }
        else
        {
            e.Effect = DragDropEffects.None;
        }
    }

private void dataGridView1_DragDrop(object sender, DragEventArgs e)
    {
        BindingList<Datei> droppedDateien = e.Data.GetData(DataFormats.FileDrop) as BindingList<Datei>;

        if (droppedDateien.Count() > 0) //this block does not execute.
        {
            foreach (Datei datei in draggedDateienlist)
            {
                dateienList.Add(datei);
            }
        }
    }

However, I checked nothing happens in DragDrop function. Why is that?

1

There are 1 answers

2
dr.null On BEST ANSWER

As I understand your code snippet, you are not doing internal drag & drop (DoDragDrop), I think you want to drag external files from the File Explorer for example and drop them into the grid. Accordingly,

You are doing wrong cast here:

BindingList<Datei> droppedDateien = e.Data.GetData(DataFormats.FileDrop) as BindingList<Datei>;

e.Data.GetData(DataFormats.FileDrop) method returns string[] not BindingList<T>.

So, cast to the right type, create new Datei objects, and add them to the dateienList.

private void dataGridView1_DragEnter(object sender, DragEventArgs e)
{
    e.Effect = e.Data.GetDataPresent(DataFormats.FileDrop)
        ? DragDropEffects.Copy
        : DragDropEffects.None;
}

private void dataGridView1_DragDrop(object sender, DragEventArgs e)
{
    if (e.Data.GetData(DataFormats.FileDrop) is string[] files)
        AddFiles(files);
}

// Also, you can copy & paste...
private  void PasteButton_Click(object sender, EventArgs e)
{
    if (Clipboard.GetData(DataFormats.FileDrop) is string[] files)
        AddFiles(files);
}

private void AddFiles(string[] files)
{
    foreach (var file in files)
    {
        if (!dateienList.Any(x => x.FullName.Equals(
            file, StringComparison.OrdinalIgnoreCase)))
        {
            dateienList.Add(new Datei
            {
                Name = Path.GetFileName(file),
                FullName = file
            });
        }
    }
}

// For example...
public class Datei
{
    public string Name { get; set; }
    public string FullName { get; set; }

    public override string ToString() => Name;
}

Just in case, if you are doing internal drag & drop like moving rows from one grid to another:

private void SourceDGV_MouseMove(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left && 
        SourceDGV.SelectedRows.Count > 0)
    {
        var items = SourceDGV.SelectedRows.Cast<DataGridViewRow>()
            .Select(r => r.DataBoundItem as Datei).ToArray();
        DoDragDrop(items, DragDropEffects.Move);
    }
}

private void DestinationDGV_DragOver(object sender, DragEventArgs e)
{
    e.Effect = e.Data.GetDataPresent(typeof(Datei[]))
        ? DragDropEffects.Move
        : DragDropEffects.None;
}

private void DestinationDGV_DragDrop(object sender, DragEventArgs e)
{
    if (e.Data.GetData(typeof(Datei[])) is Datei[] items)
    {
        // ...
    }
}