Получить выбранный столбец из GTK# NodeView

#c# #monodevelop #gtk#

#c# #monodevelop #gtk#

Вопрос:

Я пишу некоторый код на C # на Raspberry Pi, используя MonoDevelop. У меня есть NodeView виджет, который содержит три столбца. Я хотел бы определить столбец, на который был нажат в NodeView. Я пытался использовать NodeSelection.Changed , но это не говорит мне о столбце. Я также попытался закодировать ButtonPress событие для NodeView и перейти к TreePath . С этим я ничего не добился.

Я заметил, что этот вопрос задавался несколько раз. Но я не видел прямого способа получить строку / столбец для выбранного элемента в NodeView .

Кто-нибудь знает, как это сделать?

Ответ №1:

Наконец-то разобрался. Это была боль, потому что, как вы сказали, документации по этому вопросу нет.

Итак, чтобы описать, что я сделал, вот как выглядит мое окно: программа

Когда я нажимаю на разные столбцы, это вывод:

 Clicked on column index 3 with title "hello 3"
Node selected: Prop1 29478338;Prop2 55998661;Prop3 1058200043;Prop4 1429485106
Clicked on column index 2 with title "hello 2"
Node selected: Prop1 1781730137;Prop2 618078535;Prop3 1253079243;Prop4 1149116957
Clicked on column index 1 with title "hello 1"
Node selected: Prop1 1577113328;Prop2 1907291485;Prop3 764000225;Prop4 1871218984
Clicked on column index 0 with title "hello 0"
Node selected: Prop1 1267506574;Prop2 692394441;Prop3 1291543143;Prop4 41456018
Clicked on column index 1 with title "hello 1"
Node selected: Prop1 1659363497;Prop2 873230641;Prop3 1799765877;Prop4 83248840
Clicked on column index 2 with title "hello 2"
Node selected: Prop1 1882743696;Prop2 419098689;Prop3 554049937;Prop4 671882960
  

И код, каким бы «не симпатичным» он ни был (просто быстро добавляю материал, чтобы заставить его работать):

 Random r = new Random();

[Gtk.TreeNode(ListOnly = true)]
public class MyTreeNode : Gtk.TreeNode
{
    public MyTreeNode(Random r)
    {
        AnotherProp1 = $"Prop1 {r.Next()}";
        AnotherProp2 = $"Prop2 {r.Next()}";
        AnotherProp3 = $"Prop3 {r.Next()}";
        AnotherProp4 = $"Prop4 {r.Next()}";
    }

    [Gtk.TreeNodeValue(Column = 0)]
    public string AnotherProp1 { get; private set; }

    [Gtk.TreeNodeValue(Column = 1)]
    public string AnotherProp2 { get; private set; }

    [Gtk.TreeNodeValue(Column = 2)]
    public string AnotherProp3 { get; private set; }

    [Gtk.TreeNodeValue(Column = 3)]
    public string AnotherProp4 { get; private set; }

    public override string ToString() =>
        $"{AnotherProp1};{AnotherProp2};{AnotherProp3};{AnotherProp4}";
}

private readonly NodeStore _store = new NodeStore(typeof(MyTreeNode));

public MainWindow() : base(Gtk.WindowType.Toplevel)
{
    Build();

    for (var i = 0; i < 6;   i)
    {
        _store.AddNode(new MyTreeNode(r));
    }
    nodeview2.NodeStore = _store;

    nodeview2.AppendColumn("hello 0", new CellRendererText(), "text", 0).Clickable = true;
    nodeview2.AppendColumn("hello 1", new CellRendererText(), "text", 1).Clickable = true;
    nodeview2.AppendColumn("hello 2", new CellRendererText(), "text", 2).Clickable = true;
    nodeview2.AppendColumn("hello 3", new CellRendererText(), "text", 3).Clickable = true;

    // how to detect column header clicks:
    nodeview2.GetColumn(0).Clicked  = (s, e) => Console.WriteLine("HERE 0");
    nodeview2.GetColumn(1).Clicked  = (s, e) => Console.WriteLine("HERE 1");
    nodeview2.GetColumn(2).Clicked  = (s, e) => Console.WriteLine("HERE 2");
    nodeview2.GetColumn(3).Clicked  = (s, e) => Console.WriteLine("HERE 3");

    nodeview2.WidgetEvent  = (s, e) =>
    {
        if ((e.Event is Gdk.EventButton ev) amp;amp;
           (ev.Type == Gdk.EventType.ButtonPress) amp;amp;
           (ev.Window == nodeview2.BinWindow))
        {
            if (nodeview2.GetPathAtPos((int)ev.X, (int)ev.Y, out var path, out var column))
            {
                // get the column index. There must be a better way?
                var columnIndex = nodeview2.Columns.Select(
                    (col, index) => new { col, index }).First(x => ReferenceEquals(x.col, column)).index;

                Console.WriteLine($"Clicked on column index {columnIndex} with title "{column.Title}"");

                var nodeValue = (MyTreeNode)_store.GetNode(path);
                Console.WriteLine($"Node selected: {nodeValue}");
            }
        }
    };

    nodeview2.ShowAll();
}
  

Итак, хитрость здесь в том, чтобы перехватить EventButton ‘s ButtonPress , затем взять координаты и передать их GetPathAtPos() . Который возвращает информацию о столбце и пути. Вы можете использовать это, чтобы получить то, что вам нужно. Хотелось бы, чтобы Gtk # был лучше документирован / более широко использовался.

Комментарии:

1. Спасибо за это. Я постараюсь реализовать то, что вы предлагаете, и отчитаюсь.

2. Еще раз спасибо. Это решило мою проблему. Теперь я могу определить щелчок по определенному столбцу в NodeView.

3. @rrirower — нет проблем. рад, что это сработало. Если у вас возникнут какие-либо другие проблемы, я был бы более чем счастлив разобраться в них. Удачи!