TreeView触发DragEnter,DragOver和DragLeave事件,但不会触发DragDrop

时间:2011-02-22 14:09:06

标签: c# .net drag-and-drop

冰雹堆!

我很难弄清楚为什么我的树视图(或任何其他组件,甚至表单本身)都不会触发事件DragDrop。

我已经确定了这样的表格:
内部带有面板表单 Panel有一个 TreeView ,这个TreeView( MyTree )具有以下代码:

MyTree.AllowDrop = true;
MyTree.DragDrop += new System.Windows.Forms.DragEventHandler(onDragDrop);
MyTree.DragEnter += new System.Windows.Forms.DragEventHandler(onDragEnter);
MyTree.DragLeave += new System.EventHandler(onDragLeave);
MyTree.DragOver += new System.Windows.Forms.DragEventHandler(onDragOver);

处理程序看起来像这样:

private void onDragEnter(object sender, DragEventArgs e)
{
    Console.WriteLine(" === DragEnter === ");
}

private void onDragLeave(object sender, EventArgs e)
{
    Console.WriteLine(" === DragLeave === ");
}

private void onDragOver(object sender, DragEventArgs e)
{
    Console.WriteLine(" === DragOver === ");
}

private void onDragDrop(object sender, DragEventArgs e)
{
    Console.WriteLine(" === DragDrop === ");
}

当我测试我的应用时,拖动* .txt文件(或任何东西)的输出类似于:

=== DragEnter ===
=== DragOver ===
=== DragOver ===
...
=== DragOver ===
=== DragLeave ===

最后一行(=== DragLeave ===)并不意味着离开事件 实际上,当我在TreeView上释放鼠标按钮时会打印这一行。

我在做一些非常错误的事情?

3 个答案:

答案 0 :(得分:2)

这是我用于拖放到文件的树视图中的内容:

public class DragDropManager
{
    private UserControl _parent;

    private AddFilesEventHandler OnAddFiles;   

    public DragDropManager()
    {
    }

    public UserControl Parent
    {
        set
        {
            _parent = value;    

            if ( ! ( _parent is IDropFileTarget ) )
            {
                throw new Exception("DragDropManager: Parent usercontrol does not implement IDropFileTarget interface");
            }

            OnAddFiles = new AddFilesEventHandler(((IDropFileTarget)_parent).AddFiles);
            _parent.AllowDrop = true;
            _parent.DragEnter += new System.Windows.Forms.DragEventHandler(this.OnDragEnter);
            _parent.DragDrop += new System.Windows.Forms.DragEventHandler(this.OnDragDrop);
        }
    }

    /// <summary>
    /// Handle parent form DragEnter event
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void OnDragEnter(object sender, System.Windows.Forms.DragEventArgs e)
    {
        string[] formats = e.Data.GetFormats(true);

        //e.Effect = DragDropEffects.All;

        for (int formatIndex = 0; formatIndex < formats.Length; formatIndex++)
        {
            switch (formats[formatIndex])
            {
                case Consts.DragDropFormats.FileDrop:
                    e.Effect = DragDropEffects.Copy;
                    break;
                case Consts.DragDropFormats.Text:
                    e.Effect = DragDropEffects.Move;
                    break;
                case Consts.DragDropFormats.UniformResourceLocator:
                    e.Effect = DragDropEffects.Link;
                    break;
            }
        }
    }

    /// <summary>
    /// Handle parent form DragDrop event
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void OnDragDrop(object sender, System.Windows.Forms.DragEventArgs e)
    {
        try
        {
            string[] formats = e.Data.GetFormats(true);
            string[] values = new string[1];
            string url = string.Empty;

            for (int formatIndex = 0; formatIndex < formats.Length; formatIndex++)
            {
                switch (formats[formatIndex])
                {
                    case Consts.DragDropFormats.FileDrop:
                        Array itemList = (Array)e.Data.GetData(Consts.DragDropFormats.FileDrop);

                        if (itemList != null)
                        {
                            _parent.BeginInvoke(OnAddFiles, new Object[] { itemList });
                            _parent.Focus();
                        }
                        break;
                    case Consts.DragDropFormats.Text:
                    case Consts.DragDropFormats.UniformResourceLocator:
                        values[0] = e.Data.GetData(Consts.DragDropFormats.Text).ToString();
                        _parent.BeginInvoke(OnAddFiles, new Object[] { values });
                        _parent.Focus();
                        break;
                    default:
                        break;
                }
            }
        }
        catch (Exception ex)
        {
            Trace.WriteLine("Error in DragDropManager.OnDragDrop function: " + ex.Message);
        }
    }

}

您可以按如下方式使用它:

DragDropManager dragDropManager = new DragDropManager();
dragDropManager.Parent = this;

并且需要在UserControl上实现它

public interface IDropFileTarget
{
    void AddFiles(Array Files);
}

答案 1 :(得分:1)

您需要将e.Effect中的DragOver设置为None以外的其他内容,以告知系统您愿意被放弃。

答案 2 :(得分:0)

您需要确保所拖动的项目中确实有一些数据。使用

获取当前内容的字符串数组
e.Data.GetFormats()

使用字符串数组'fmt'的每个元素作为GetData的参数

e.Data.GetData(fmt)

如果它们全为空,则不会触发DragDrop事件,也没有设置e的效果。Effect不会改变它。如果确定这是原因,则可以更具体地寻找根本原因。 (对于我来说是Internet Explorer)