creating nodes and edges by clicking and dragging

Aug 31, 2012 at 3:55 AM

Can I do the following with graph#

creating nodes by click on canvas

creating edges between two vertices with mouse

change color of edges during the run time

handle click event of nodes during the run time

I could not find any documentation on graph# so that will be great if someone can provide me some tips.

Thanks

Aug 31, 2012 at 6:45 AM

HI all,

that is exactly the same feature I'm trying to achieve. Can any Graph#-Gurus help here?

Nov 29, 2012 at 8:19 PM

same question here

Nov 30, 2012 at 1:11 PM
Edited Dec 17, 2012 at 4:16 PM

You can do all of those things with Graph#, they are more general WPF than specific Graph# issues, though.

Creating nodes by clicking on canvas: Add an event handler for the mouse even that you want to cause the adding of a node (right-click for example) to the ZoomControl. I personally don't do this but add a context menu to the ZoomControl and a menu option in there to add a node:

 

<zoom:ZoomControl   ..... > 
<!-- the graphlayout -->
   <zoom:ZoomControl.ContextMenu>
         <ContextMenu>
               <MenuItem Header="Add Node" Click="AddNodeMenuClick"/>
                <!-- other menus-->
           </ContextMenu>
     </zoom:ZoomControl.ContextMenu>
</zoom:ZoomControl>

 

In the AddNodeMenuClick handler you ask the user for all the information you need in order to create a node (its name etc.) using a dialog or some other input form. I use a ChildWindow from the WpfToolkit.Extended library (http://wpftoolkit.codeplex.com/wikipage?title=ChildWindow&referringTitle=Documentation) that looks like this:

 

      <xctk:ChildWindow Name="addVertexWindow" Caption="Add Vertex" IsModal="True" WindowStartupLocation="Center">
            <Grid Margin="10" >
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>

                <TextBlock Grid.Row="0" Text="Table Name: " Margin="2" VerticalAlignment="Center" />
                <TextBox Name="tableNameBox" Grid.Row="1" Margin="2"/>

                <StackPanel Grid.Row="2"  Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,10,0,0">
                    <Button Margin="2" Click="ConfirmAddVertexButtonClick" Content="Confirm"/>
                    <Button Margin="2" Click="CancelButtonClick" Content="Cancel"/>
                </StackPanel>
            </Grid>
        </xctk:ChildWindow>

 

The AddNodeMenuClick handler just opens this child window (or whatever else you want to use, a MessageBox might be enough):

 

private void AddNodeMenuClick(object sender, RoutedEventArgs e)
{
       addVertexWindow.Show();
}

 

Of course you will probably have more than just the table name to ask for. Here's the handler for the Confirm button, 'vm' is the MainWindowViewModel instance.

 

private void ConfirmAddVertexButtonClick(object sender, RoutedEventArgs e)
        {
            if (tableNameBox.Text == String.Empty)
            {
                MessageBox.Show("No table name provided");
                return;
            }

             MyVertex newVertex = new MyVertex(tableNameBox.Text);
             vm.Graph.AddVertex(newVertex);
             addVertexWindow.Close();         
        }

I don't have any code to show creating edges between two vertices with mouse, but it should be possible again, by adding handlers tot he mouse events on VertexControls. Changing colors of vertices and edges can be done by having the MyVertice and MyEdge classes (or whatever they are called for you) have a Color property that notifies when it is changed like so:

 

    public class MyEdge : Edge<MyVertex>, INotifyPropertyChanged
    {
        //.......
        private Color edgeColour;
        public Color EdgeColour
        {
            get { return edgeColour; }
            set
            { 
                edgeColour = value;
                NotifyPropertyChanged("EdgeColour");
            }
        }
        //.......

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(string info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
    }

Once you have that you can add a Setter in the EdgeControl's style that looks something like this:

<Setter Property="Foreground" Value="{Binding Path=EdgeColour, Converter={StaticResource MyConverter}}">

 

 

The converter is there because the Foreground property doesn't take a Color but a Brush, so in the converter you just need to return a SolidColorBrush with the specified color. Now you just need to be able to change the EdgeColour property at runtime. Again, I'm using the ColorPicker control from the WpfToolkit.Extended library inside a ChildWindow, which is opened when a context menu option is clicked.

 

        <xctk:ChildWindow Name="individualColourWindow" Caption="Choose Foreground Colour" IsModal="True" WindowStartupLocation="Center">
            <Grid Margin="10" >
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>

                <TextBlock Grid.Row="0" Text="Choose Colour:" Margin="2" VerticalAlignment="Center" />
                <xctk:ColorPicker Name="individualColour" Grid.Row="0" Grid.Column="1" Margin="2" SelectedColor="Black" DisplayColorAndName="True" />

                <StackPanel Grid.Row="1" Grid.ColumnSpan="2" Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,10,0,0">
                    <Button Width="65" Margin="2" Click="OkIndividualColourButtonClick" Content="OK"/>
                    <Button Width="65" Margin="2" Click="CancelButtonClick" Content="Cancel"/>
                </StackPanel>
            </Grid>
        </xctk:ChildWindow>

 

The OkIndividualColourButton handler:

 

        private void OkIndividualButtonClick(object sender, RoutedEventArgs e)
        {
            EdgeControl ec = ((sender as MenuItem).Parent as ContextMenu).PlacementTarget as EdgeControl;
            (ec.Edge as ERDEdge).EdgeColour = individualColour.SelectedColor;
            individualColourWindow.Close();
        }

Also look at this: http://graphsharp.codeplex.com/discussions/399641