【问题标题】:WPF Drag and Drop object from listboxWPF 从列表框中拖放对象
【发布时间】:2016-12-27 02:15:32
【问题描述】:

这里是初学者。

我正在尝试创建一个用户控件,其中包含一个列表框和其他控件,我希望此列表框允许拖放到用户控件的其他类似实例。

这是我想从一个列表框拖放到另一个列表框的对象:

[Serializable]
public class ListBoxFileName : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }

    private string FileNameValue;
    public string FileName
    {
        get { return this.FileNameValue; }

        set
        {
            if (value != this.FileNameValue)
            {
                this.FileNameValue = value;
                NotifyPropertyChanged("FileName");
            }
        }
    }

    private bool FileIsSelectedValue;
    public bool FileIsSelected
    {
        get { return this.FileIsSelectedValue; }

        set
        {
            if (value != this.FileIsSelectedValue)
            {
                this.FileIsSelectedValue = value;
                NotifyPropertyChanged("FileIsSelected");
            }
        }
    }
}

这是我处理拖放的方式:

    private ListBoxItem _dragged;

    private void FileNameList_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        if (_dragged != null)
            return;

        UIElement element = FileNameList.InputHitTest(e.GetPosition(FileNameList)) as UIElement;
        while (element != null)
        {
            if (element is ListBoxItem)
            {
                _dragged = (ListBoxItem)element;
                break;
            }
            element = VisualTreeHelper.GetParent(element) as UIElement;
        }
    }


    private void Window_MouseMove(object sender, MouseEventArgs e)
    {
        if (_dragged == null)
            return;
        if (e.LeftButton == MouseButtonState.Released)
        {
            _dragged = null;
            return;
        }
        DataObject obj = new DataObject(DataFormats.Serializable, _dragged);
        DragDrop.DoDragDrop(_dragged, obj, DragDropEffects.All);
    }

    private void FileNameList_DragEnter(object sender, DragEventArgs e)
    {
        if (_dragged == null || e.Data.GetDataPresent(DataFormats.Serializable, true) == false)
            e.Effects = DragDropEffects.None;
        else
            e.Effects = DragDropEffects.All;
    }

    private void FileListBox_Drop(object sender, DragEventArgs e)
    {
        if (e.Data.GetDataPresent(DataFormats.FileDrop, true))
        {
            string[] droppedFilePaths = e.Data.GetData(DataFormats.FileDrop, true) as string[];
            for (var i = 0; i < droppedFilePaths.Length; i++)
            {
                ListBoxFileName filename = new ListBoxFileName();
                filename.FileName = droppedFilePaths[i];
                filename.FileIsSelected = false;
                FileNamesItems.Add(filename);
            }
        }
        if (e.Data.GetDataPresent(DataFormats.Serializable, true))
        {
            ListBoxFileName BoxItem = new ListBoxFileName();
            BoxItem = e.Data.GetData(DataFormats.Serializable) as ListBoxFileName;
        }
    }

一切都很好,除非发生 drop 事件,BoxItem 由于某种原因始终为空,因此没有任何内容添加到列表框中。

有什么提示吗?

谢谢

【问题讨论】:

  • 你尝试过来自nuget.org/packages/gong-wpf-dragdrop 的 gon-wpf-dragdrop 吗?源代码也是可用的,所以你可以看看它是如何实现的
  • @bamanow,gong-wpf的nuget依赖于WPFToolkit包,而这个包依赖于.NET 3.5。它与 .NET 4.0 或更高版本不兼容。
  • @Eriawan 你错了,从 .NET 4.0 开始它没有任何依赖项

标签: c# wpf


【解决方案1】:

DataObject 的数据应该是 ListBoxFileName 而不是 ListBoxItem:

private void Window_MouseMove(object sender, MouseEventArgs e)
{
    if (_dragged == null)
        return;
    if (e.LeftButton == MouseButtonState.Released)
    {
        _dragged = null;
        return;
    }
    DataObject obj = new DataObject(DataFormats.Serializable, _dragged.DataContext as ListBoxFileName);
    DragDrop.DoDragDrop(_dragged, obj, DragDropEffects.All);
}

private void FileListBox_Drop(object sender, DragEventArgs e)
{
    if (e.Data.GetDataPresent(DataFormats.Serializable, true))
    {
        ListBoxFileName BoxItem = e.Data.GetData(DataFormats.Serializable) as ListBoxFileName;
        //...
    }
}

假设“FileNameList”控件的 ItemsSource 设置为 IEnumerable,这应该可以工作。

如果您需要任何进一步的帮助,请提供能够从头开始重现您的问题所需的所有相关代码 sn-ps。

【讨论】:

  • 感谢它“部分”工作。事实上,现在当我选择一个 BoxItem 的副本时,它会在每个列表框中被选中。知道这可能来自哪里吗?
  • 同一个 ListBoxFileName 对象是两个不同可视化容器的 DataContext,因此当您设置其 IsSelected 属性(或您所称的任何内容)时,两个容器将被选中,因为它们绑定到相同的属性.如果您不希望这样做,您应该在将 ListBoxFileName 对象添加到第二个 ListBox 之前对其进行克隆,即创建一个副本。
  • 太好了。请记住接受答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-07
  • 1970-01-01
  • 1970-01-01
  • 2019-02-11
相关资源
最近更新 更多