This project is read-only.

Rename a vertex in runtime

Jun 25, 2009 at 3:30 PM

Hey guys!

I've been playing around with G# and I think im starting to get very good results, but I have a question I cant figure out.

I'm changing the text in a vertex in runtime, but I cant get the graphlayout to refresh it in the graphlayout. I thought that the "Relayout()" method would help me, but it doesnt. It keeps showing the old value. How can I update my graph view?

 

TY!

Jun 27, 2009 at 1:45 PM

Hi!

The reasons that it doesn't work:

  • i think your vertex does not implement the INotifyPropertyChanged interface, so the UI doesn't get any notification about the text changing
  • the relayout method does not creates new controls for the vertices (only for the new vertices, or it removes the deleted ones), so the same UI controls will show the vertex after you call the Relayout method

What you can do, to solve your problem:

  • Brute-force solution:
    yourLayoutControl.Graph = null; //at this point the vertexcontrols will be purged
    yourLayoutControl.Graph = yourGraph; //at this point new vertexcontrols will be created
    
  • "Elegant way": implement the INotifyPropertyChanged method in your vertex-type or modify the datatemplate of the vertices

palesz

Jun 27, 2009 at 3:41 PM
Edited Jun 27, 2009 at 5:22 PM

I don have implemented that interface as you well say. Im trying to figure out how to make it work but im not getting many results, could you show me a simple sample of how to make it work?

 

This is what I have

class State: INotifyPropertyChanged {
    public string nameValue;
    public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

private void NotifyPropertyChanged(String info) { if (PropertyChanged != null) PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(info)); } public string name { get { return this.nameValue; } set {
if (value != this.nameValue) this.nameValue = value; } } }
which I use as vertex and I change the name property a form in the application. So what should I write in the graph-section of
the code so that the graph updates the names?

foreach (State s in state)
{
    s.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(s_PropertyChanged);
    g.AddVertex(s);
}

void s_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
    ????
}
Jun 27, 2009 at 9:23 PM

 

class State: INotifyPropertyChanged {
    public string nameValue;
    public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(info));
    }

    public string name
    {
        get { return this.nameValue; }
        set
        {
            if (value != this.nameValue) {
                this.nameValue = value;
                NotifyPropertyChanged("name"); //this is the MISSING LINE!!!
            }
         }
    }
}

 

Jun 28, 2009 at 2:21 AM

Still nothing :( I will copy the whole code so that you see what Im dealing with. First the State.cs

namespace PFCEditor
{
    class State:System.ComponentModel.INotifyPropertyChanged
    {
        public int id;
        public string nameValue;

        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(info));
            }
        }

        public string name
        {
            get
            {
                return this.nameValue;
            }
           
            set
            {
                if (value != this.nameValue)
                {
                    this.nameValue = value;
                    NotifyPropertyChanged("name");
                }
            }
        }


        public State(int id, string name)
        {
            this.id = id;
            this.name = name;
        }

        public override string ToString()
        {
            return this.name;
        }
    }
}

and now the UserControl with the diagram

    public partial class Diagram : UserControl
    {
        public BidirectionalGraph<object, IEdge<object>> _graphtovisualize;
       
        public BidirectionalGraph<object, IEdge<object>> GraphToVisualize
        {
            get { return _graphtovisualize; }
        }

        public Diagram(string filename)
        {
            CreateNewGraph();
            InitializeComponent();
        }

        private void CreateNewGraph()
        {

            //BLABLABLA. Picking up info on the states...

            foreach (State s in state)
            {
                s.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(s_PropertyChanged);
                g.AddVertex(s);
            }

            foreach (Edge<object> e in edge)
            {
                g.AddEdge(e);
            }

            this._graphtovisualize = g;
        }

        void s_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
               //Not sure what to put here...
        }
    }
}

Jun 28, 2009 at 9:18 AM

Ok, now i see the real problem, you don't have a DataTemplate for the state class. So in the XAML file of your UserControl add those things:

 

<UserControl ...
                    xmlns:myns="clr-namespace:PCFEditor[OPTIONALLY needed this: ;assembly=assembly_name_which_contains_your_state_class_if_its_not_the_same_as_your_usercontrol's_assemlby_(without_dll_postfix)]">
    <UserControl.Resources>
    <!-- define with a datatemplate how to show your state class-->
    <DataTemplate DataType="{x:Type myns:state}">
        <TextBlock Text="{Binding Path=name,Mode=OneWay}"/>
    </DataTemplate>
    </UserControl.Resources>

    <!-- here is the GraphLayout Control -->
</UserControl>

and beside that you  need to make your state class public and you don't need the 

 

s.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(s_PropertyChanged);

line and the

 

void s_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
               //Not sure what to put here...
        }

event handler method, the WPF knows how to handle the INotifyPropertyChanged interface, you only needed to implement the interface the WPF take care of the changes (changing the text, ... via the Binding)

 

 

 

Jun 28, 2009 at 1:27 PM

I love you, dude :) Thanks for the support :)