locked
[BUG]: Node.UserData is not actually populated when retrieving the gViewer.SelectedObject in the Mouseclick Event RRS feed

  • Question

  • I'm surprised this hasn't been spotted before as its fundamental that nodes should retain data, otherwise they're just decoration.

    Code to replicate:

    // nodes array and graphViewer objects created and initialized before we get here 
    private void DrawNode(Graph g, Node[] nodes)
     {
         foreach (Node n in nodes)
         {   
             // I'm assigning an object to UserData in the actual code, but this implicit cast demonstrates the principle too
             n.UserData = "some user data";
             g.AddNode(n.Id);
             // can confirm here that node has unique Id and
             // userdata is populated
         }
     gViewer.Graph = g;
     }

    But when you try to retrieve the Node clicked under the mouse (for example to display its data in the adjacent WindowsApplication PropertyGrid):

    void gViewer_MouseClick(object sender, MouseEventArgs e)
    {
        if (e.Button == System.Windows.Forms.MouseButtons.Left && selectedObject is Microsoft.Msagl.Drawing.Node)
        {               
            this.propertyGrid1.SelectedObject =  (gViewer.SelectedObject as Node).UserData;
        }
    }

    The following UserData is always null.

    (gViewer.SelectedObject as Node).UserData

    Sunday, February 24, 2013 5:41 PM

Answers

  • Lito

    I just noticed that you are calling g.AddNode(n.Id);
    This creates a new node with UserData set to null.

    The right usage of the API is something like

    var myNode=g.AddNode(id);

    Thanks,

    Lev


    Lev Nachmanson

    Sunday, March 3, 2013 5:15 PM

All replies

  • I was unable to reproduce it, so I asked Lito for a repro

    Lev Nachmanson

    Sunday, March 3, 2013 12:33 AM
  • I've just tried to re-create it in a simple program based on your Windows Application sample and I cannot reproduce it. It still does not work in my code though and there is one crucial difference between my code and the sample.

    In my code, I am constructing my own objects which are populated with XML data to put into UserData - does Node.UserData support complex object types or just a string type?

    (Of course, if that is a limitation, I can serialize it and read it back in but I'll just need to take the performance hit).

    Thanks for your help so far.


    • Edited by Lito Athr Sunday, March 3, 2013 11:28 AM
    Sunday, March 3, 2013 11:27 AM
  • Lito

    I just noticed that you are calling g.AddNode(n.Id);
    This creates a new node with UserData set to null.

    The right usage of the API is something like

    var myNode=g.AddNode(id);

    Thanks,

    Lev


    Lev Nachmanson

    Sunday, March 3, 2013 5:15 PM
  • Lito

    I just noticed that you are calling g.AddNode(n.Id);
    This creates a new node with UserData set to null.

    The right usage of the API is something like

    var myNode=g.AddNode(id);

    Thanks,

    Lev


    Lev Nachmanson

    Lev, that wasn't the problem, because I had already confirmed that the UserData was being populated in that first block.

    The following works fine if you substitute this code in the windowsApplicationSample Form1 application, so I conclude that this was my scoping error (I think I wasn't making the node details accessible correctly).

    Thanks for your help but this is not a bug, it was my error - sorry.

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using Microsoft.Msagl.Drawing; namespace NetNodeDemo { public partial class Form1 : Form { ToolTip toolTip1 = new ToolTip(); public Form1() { this.Load += new EventHandler(Form1_Load); InitializeComponent(); this.toolTip1.Active = true; toolTip1.AutoPopDelay = 5000; toolTip1.InitialDelay = 1000; toolTip1.ReshowDelay = 500; // Force the ToolTip text to toolTip1.ShowAlways = true; } void Form1_Load(object sender, EventArgs e) { gViewer.MouseClick += new MouseEventHandler(gViewer_MouseClick); } void gViewer_MouseClick(object sender, MouseEventArgs e) { if (e.Button == System.Windows.Forms.MouseButtons.Left && gViewer.SelectedObject is Microsoft.Msagl.Drawing.Node) { propertyGrid1.SelectedObject = (gViewer.SelectedObject as Node).UserData; } } private void button1_Click(object sender, EventArgs e) { Graph graph = new Graph("graph"); NetworkNode[] netNodes = new NetworkNode[2]; netNodes[0] = new NetworkNode(); netNodes[0].Host = "Host1"; netNodes[0].Ipaddress = "127.0.0.1"; netNodes[0].IsUp = true; netNodes[0].Mac = "DE:AD:BE:EF:A1"; netNodes[1] = new NetworkNode(); netNodes[1].Host = "Host2"; netNodes[1].Ipaddress = "127.0.0.2"; netNodes[1].IsUp = false; netNodes[1].Mac = "2B:AC:C0:DE:B8"; foreach (NetworkNode node in netNodes) { Node n = new Node(node.Ipaddress); n.UserData = node; graph.AddNode(n); } gViewer.Graph = graph; // graph generation ends here } private static void CreateSourceNode(Node a) { a.Attr.Shape = Microsoft.Msagl.Drawing.Shape.Box; a.Attr.XRadius = 3; a.Attr.YRadius = 3; a.Attr.FillColor = Microsoft.Msagl.Drawing.Color.Green; a.Attr.LineWidth = 10; } private void CreateTargetNode(Node a) { a.Attr.Shape = Microsoft.Msagl.Drawing.Shape.DoubleCircle; a.Attr.FillColor = Microsoft.Msagl.Drawing.Color.LightGray; a.Attr.LabelMargin = -4; } private void recalculateLayoutButton_Click(object sender, EventArgs e) { this.gViewer.Graph = this.propertyGrid1.SelectedObject as Microsoft.Msagl.Drawing.Graph; } public class NetworkNode { private string host; private string ipaddress; private string mac; private bool isup; [Category("Host Information"), Description("Host Name")] public string Host { get { return host; } set { host = value; } } [Category("Host Information"), Description("IP Address")] public string Ipaddress { get { return ipaddress; } set { ipaddress = value; } } [Category("Host Information"), Description("MAC Address")] public string Mac { get { return mac; } set { mac = value; } } [Category("Host Information"), Description("Host Running")] public bool IsUp { get { return isup; } set { isup = value; } } } } }


    • Edited by Lito Athr Sunday, March 3, 2013 7:22 PM
    Sunday, March 3, 2013 6:30 PM