Как я могу прослушивать DragDataReceived в TreeView, когда модель является TreeModelSort? - PullRequest
1 голос
/ 20 декабря 2010

У меня есть TreeView, модель которого является TreeModelSort с ListStore в качестве дочернего.Я хотел бы, чтобы это TreeView слушало DragDataReceived.Однако когда я перетаскиваю данные в него, я получаю это предупреждение:

(TestDragDrop: 4706): Gtk-WARNING **: вы должны переопределить обработчик по умолчанию «drag_drop» в GtkTreeView при использовании моделей, которыене поддерживает интерфейс GtkTreeDragDest и не допускает перетаскивание.Самый простой способ сделать это - подключиться к drag_drop и вызвать g_signal_stop_emission_by_name () в вашем обработчике сигналов, чтобы предотвратить запуск обработчика по умолчанию.Посмотрите исходный код обработчика по умолчанию в gtktreeview.c, чтобы понять, что должен делать ваш обработчик.(gtktreeview.c находится в исходном коде GTK.) Если вы используете GTK из языка, отличного от C, может быть более естественный способ переопределить обработчики по умолчанию, например, путем деривации.

Я немного растерялся, как это сделать в Gtk #.В сообщении говорится: «Если вы используете GTK из языка, отличного от C, может быть более естественный способ переопределить обработчики по умолчанию, например, путем деривации».Может кто-нибудь указать мне пример того, как это будет выглядеть?Что именно я переопределяю?Нет метода 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 Ответ

2 голосов
/ 14 февраля 2011

Обработчиком по умолчанию для drag_drop в Gtk # является Widget.OnDragDrop. Поэтому вам нужно будет создать подкласс TreeView и переопределить этот виртуальный метод, чтобы исключить встроенный в TreeView механизм TreeDragDest.

Эта подпись для OnDragDrop:

защищенный виртуальный bool OnDragDrop (контекст Gdk.DragContext, int x, int y, время uint _)

...