GTK# Nodeview Nodestore всегда получает нулевую ссылку

Я создал GTK# Nodeview + NodeStore, следуя коду на странице руководства по GTK# Mono! Мои изменения заключались в добавлении кнопки «Добавить новые записи в NodeView» и попытке сделать ее интерактивной. Моя проблема заключается в том, что событие NodeView Selection Changed приводит к сбою приложения.

using System;
using Gtk;

public partial class MainWindow : Window
{
    Button button;
    NodeView nodeview;
    NodeStore nodestore;

    [TreeNode(ListOnly = true)]
    public class MyTreeNode : TreeNode
    {
        public MyTreeNode(string artist)
        {
            Artist = artist;
        }

        [TreeNodeValue(Column = 0)]
        public string Artist;
    }


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

        var vbox = new VBox();
        nodeview = new NodeView();
        // Create a column with title Artist and bind its renderer to model column 0
        nodeview.AppendColumn("Artist", new CellRendererText(), "text", 0);

        nodestore = new NodeStore(typeof(MyTreeNode));
        nodestore.AddNode(new MyTreeNode("temp"));
        nodeview.NodeStore = nodestore;

        nodeview.Selection.Changed += Selection_Changed;

        button = new Button("Add New!!");
        button.Clicked += Button_Clicked;

        vbox.PackStart(nodeview, true, true, 0);
        vbox.PackStart(button, false, true, 0);

        Add(vbox);
        ShowAll();
    }

    void Button_Clicked(object sender, EventArgs e)
    {
        nodestore.AddNode(new MyTreeNode("temp"));
    }

    void Selection_Changed(object sender, EventArgs e)
    {
        NodeSelection selection = (NodeSelection)sender;
        if (selection != null)
        {
            MyTreeNode node = (MyTreeNode)selection.SelectedNode;
            var a = node.Artist;
        }
    }

    protected void OnDeleteEvent(object sender, DeleteEventArgs a)
    {
        Application.Quit();
        a.RetVal = true;


    }
}

Когда я выбираю узел в NodeView, приложение вылетает без предупреждения. Затем с некоторой отладкой я понял, что при вводе NodeSelection_Changed переменная NodeStore в Nodeview всегда равна нулю. Несмотря на то, что он добавляет к нему узлы ... (они отображаются в представлении узлов).


person xDGameStudios    schedule 15.12.2017    source источник
comment
Можете привести полностью рабочий пример? Для меня не очевидно, где и когда nodeStore связан с NodeView. В примере Mono GTK# он создается и передается конструктору NodeView.   -  person Matt Ward    schedule 15.12.2017
comment
Загрузил полный пример прямо сейчас! Здесь та же проблема!   -  person xDGameStudios    schedule 15.12.2017


Ответы (1)


Похоже, это ошибка в GTK#, которая была исправлено, но не в версии, поставляемой с Mono 5.8 и старше.

Обходной путь — установить поле store в классе NodeView с помощью отражения.

typeof (NodeView).GetField ("store", BindingFlags.Instance | BindingFlags.NonPublic).SetValue (nodeview, nodestore);

Если вы добавите приведенную выше строку сразу после строки, которая устанавливает хранилище узлов в NodeView, это исправит значение NodeView.NodeStore, равное нулю.

nodeview.NodeStore = nodestore;
typeof (NodeView).GetField ("store", BindingFlags.Instance | BindingFlags.NonPublic).SetValue (nodeview, nodestore);

Также обратите внимание, что код, который у вас есть в событии Selection_Changed, не работает, потому что отправителем является Gtk.TreeSelection, а не Gtk.NodeSelection. Я изменил метод Selection_Changed следующим образом:

void Selection_Changed(object sender, EventArgs e)
{
    NodeSelection selection = nodeview.NodeSelection;
    if (selection != null)
    {
        MyTreeNode node = (MyTreeNode)selection.SelectedNode;
        var a = node.Artist;
    }
}
person Matt Ward    schedule 17.12.2017
comment
+10, если бы я мог! И ссылка на ошибку, и копия обходного пути очень полезны. Спасибо. - person Barton; 17.02.2018