当Model是TreeModelSort时,如何在TreeView中侦听DragDataReceived?

时间:2010-12-20 04:32:34

标签: c# mono gtk gtk#

我有一个TreeView,其Model是一个TreeModelSort,其中包含ListStore。我希望这个TreeView能够监听DragDataReceived。但是,当我将数据拖到它时,我收到此警告:

  

(TestDragDrop:4706):Gtk-WARNING **:   您必须覆盖默认值   GtkTreeView上的'drag_drop'处理程序   使用不支持的模型时   GtkTreeDragDest接口和   启用拖放功能。最简单的   这样做的方法是连接到   'drag_drop'并致电   g_signal_stop_emission_by_name()in   你的信号处理程序,以防止   运行默认处理程序。看着   默认的源代码   得到一个gtktreeview.c中的处理程序   想法你的处理程序应该做什么。   (gtktreeview.c在GTK源代码中   代码。)如果您正在使用GTK   C语言以外的语言可能有   更自然的方式来覆盖默认   处理程序,例如通过推导。

我在Gtk#中有点迷失方向。消息说“如果你使用的是非C语言的GTK,可能有一种更自然的方式来覆盖默认处理程序,例如通过推导。”有人能指出一个这样的例子吗?究竟我最重要的是什么?没有DragDrop方法,并且重写OnDragDataReceived似乎不起作用。或者,我可以手动对ListStore进行排序,但这似乎是一个非常糟糕的主意(特别是因为似乎没有任何简单的方法来交换元素)。

以下是一个示例TreeView供参考:

using System;
using System.Linq;
using System.Text;
using Gtk;

namespace TestDragDrop
{
    public class DestTreeView : TreeView
    {
        public DestTreeView ()
        {
            ListStore store = new ListStore (typeof (string));
            TreeModelSort sort = new TreeModelSort (store) { DefaultSortFunc = BarSortFunc };
            Model = sort;

            TreeViewColumn column = new TreeViewColumn { Title = "Bar" };
            CellRendererText cell = new CellRendererText ();
            column.PackStart (cell, true);
            column.SetCellDataFunc (cell, RenderBar);
            AppendColumn (column);

            EnableModelDragDest (Constants.Targets, Gdk.DragAction.Link);
            DragDataReceived += HandleDragDataReceived;

            store.AppendValues ("bar1");
            store.AppendValues ("bar2");
        }

        string GetValueAtPos (int x, int y)
        {
            TreePath path;
            TreeViewDropPosition pos;
            if (!GetDestRowAtPos (x, y, out path, out pos))
                return "";

            TreeIter iter;
            if (!Model.GetIter (out iter, path))
                return "";

            return (string) Model.GetValue (iter, 0);
        }

        void HandleDragDataReceived (object o, DragDataReceivedArgs args)
        {
            string text = System.Text.Encoding.UTF8.GetString (args.SelectionData.Data);
            string val = GetValueAtPos (args.X, args.Y);

            Console.WriteLine ("Data: '{0}'\nRow: '{1}'", text, val);
        }

        void RenderBar (TreeViewColumn column, CellRenderer renderer, TreeModel model, TreeIter iter)
        {
            ((CellRendererText) renderer).Text = (string) model.GetValue (iter, 0);
        }

        int BarSortFunc (TreeModel model, TreeIter iter1, TreeIter iter2)
        {
            string bar1 = (string) model.GetValue (iter1, 0);
            string bar2 = (string) model.GetValue (iter2, 0);

            return bar1.CompareTo (bar2);
        }
    }
}

1 个答案:

答案 0 :(得分:2)

Gtk#中drag_drop的默认处理程序是Widget.OnDragDrop。因此,您需要继承TreeView并覆盖该虚方法以抢占TreeView的内置TreeDragDest机制。

OnDragDrop的签名是:

protected virtual bool OnDragDrop(Gdk.DragContext context,int x,int y,uint time _)