Connector ConnectionPoints bound to view model?

9 posts, 1 answers
  1. Michael
    Michael avatar
    26 posts
    Member since:
    Oct 2014

    Posted 03 Dec 2014 Link to this post

    I need to dynamically manage the routes of connections between shapes and this includes adding/removing from the ConnectionPoints collection of the connectors.  The diagram is bound to a view-model inheriting from ObservableGraphSourceBase<> such that each connection is bound to a corresponding LinkViewModelBase<> derived class.  Is there a way to bind the ConnectionPoints collection to a property on the view model bound to each connector?  I know the ConnectionPoints can be manipulated in the code-behind, but the logic requires (ideally) unit tests to validate and therefor I would much rather be able to work with the view model.  If there is a way to do this, can someone point me in the right direction?

    Much thanks,

    Mike
  2. Michael
    Michael avatar
    26 posts
    Member since:
    Oct 2014

    Posted 03 Dec 2014 Link to this post

    Apologies, I forgot to add the following:  I did look at using a custom router.  While promising, when implementing a custom router the IRouter interface provides a single method with the following signature:

    public IList<Point> GetRoutePoints(IConnection connection, bool showLastLine)
    {
      // do stuff ....
    }

    and the router affects a single connection at a time.  Part of the issue I face is that how a connection is routed requires comparing it to other connections, for which the IRouter interface does not provide.

    Thanks.
  3. DevCraft banner
  4. Zarko
    Admin
    Zarko avatar
    755 posts

    Posted 04 Dec 2014 Link to this post

    Hi Michael,
    I'll start with your second question first - yes, by default the router doesn't know anything outside the connection that it should route but you can easily change this. As you create the router in code you can add a reference to the diagram (or your view model to it:
    this.diagram.RoutingService.Router = new MyRouter(this.diagram);
    and
    public class MyRouter : IExtendedRouter
    {
        private RadDiagram graph;
        public MyRouter(RadDiagram graph)
        {
            this.graph = graph;
        }
     
        public ConnectionRoute GetRoutePoints(IConnection connection)
        {
           //Do the routing.
        }
     
        public System.Collections.Generic.IList<Point> GetRoutePoints(IConnection connection, bool showLastLine)
        {
            var result = this.GetRoutePoints(connection);
            return result.Points;
        }
    }
    As for your original question - unfortunately at the moment we don't support bindable connection points out of the box and if you want to do this you'll need a custom attached property and some logic in its property changed. Please keep in mind that some of the diagram actions (e.g. layout) modify the points in the ConnectionsPoints collection.
    I've attached a sample project demonstrating this so you could examine it and see if it works for you.

    Regards,
    Zarko
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  5. Michael
    Michael avatar
    26 posts
    Member since:
    Oct 2014

    Posted 04 Dec 2014 Link to this post

    Fabulous!  Thank you.  This helped me use the IExtendedRouter interface after all.  But I ran into an issue trying to remove ConnectoinPoints using a custom router.  For example, I tried the following to allow the user to clear connection points from selected connectors:

      public class ConnectorClearnerRouter : IExtendedRouter
      {
        public ConnectionRoute GetRoutePoints(IConnection connection)
        {
          if (connection.IsSelected)
            return new ConnectionRoute();
          else
          {
            return new ConnectionRoute(connection.ConnectionPoints);
          }
        }
     
        public System.Collections.Generic.IList<Point> GetRoutePoints(IConnection connection, bool showLastLine)
        {
          var result = GetRoutePoints(connection);
          return result.Points;
        }
      }
     
    // Using ....
        private void btnRemoveSelectedBreaks_OnClick(object sender, RoutedEventArgs e)
        {
          diagram.RoutingService.Router = new ParallelEdgeCollapserRouter();
        }

    but ConnectionPoints were not removed.  I also tested this for all connections in the diagram, no effect.  Are there any limitations on removing connnection points?

    Thanks again!

    Mike
  6. Answer
    Zarko
    Admin
    Zarko avatar
    755 posts

    Posted 05 Dec 2014 Link to this post

    Hello Michael,
    This is strange because as far as I tested this code works. I guess that the issue is related to the scenarios in which the route method is called - if you just select an connection its update method won't be triggered and the route code won't be executed! In order to execute the code you'll have to select a connection and a shape:
    1) Run the attached project
    2) Create a connection between the shapes (note: Connections that don't have source and/or target use the RoutingService's FreeRouter)
    3) Select a shape and a connection using rectangle selection or Ctrl.
    After this the connection's connectionPoints should be cleared. If you want this to happen on single selection you could handle the selection changed event and force the update there:
    private void diagram_SelectionChanged(object sender, Telerik.Windows.Controls.SelectionChangedEventArgs e)
    {
        foreach (var item in e.AddedItems)
        {
            var connection = this.diagram.ContainerGenerator.ContainerFromItem(item) as IConnection;
            if (connection != null)
                connection.Update();
        }
    }
    (Note: this code will update the connection right after creation and will clear the ConnectionPoints)
    I hope I was able to help you and if you have more questions feel free to ask.
    p.s. Keep in mind that by default if the connection's IsModified property is true the Router won't be called for it. To change this you'll need a custom RoutingService.

    Regards,
    Zarko
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  7. Michael
    Michael avatar
    26 posts
    Member since:
    Oct 2014

    Posted 05 Dec 2014 in reply to Zarko Link to this post

    Zarko,

    Thank you for the help.  The examples helped me move forward.  Though I could not get the remove break point router working, I was able to accomplish it using code similar to the following:

    private void btnRemoveSelectedBreaks_OnClick(object sender, RoutedEventArgs e)
    {
      foreach (IConnection connection in diagram.Connections)
      {
        if (connection.IsSelected && connection.ConnectionPoints.Count > 0)
        {
           
          connection.ConnectionPoints.Clear();
          connection.Update();
        }
      }
    }

    Regards,
    Mike
  8. Zarko
    Admin
    Zarko avatar
    755 posts

    Posted 08 Dec 2014 Link to this post

    Hi Michael,
    Could you please elaborate a little bit more on the scenario that you're trying to achieve ? Do you want to remove the Connection points when you select a connection or on some other action ?

    Regards,
    Zarko
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  9. Michael
    Michael avatar
    26 posts
    Member since:
    Oct 2014

    Posted 08 Dec 2014 in reply to Zarko Link to this post

    Zarko,

    With the data I have to display, there are often parallel connections that need to be expanded and collapsed (see attached).  I need to enable the user to select a group of expanded parallel edges and then collapse them.  To collapse them, I simply iterate through each connection and remove the ConnectionPoints.  I tried using an implementation of the IRouter interface, but could not get it to be executed.  But I was able to get the required behavior by implementing the block of code in my previous post. 

    Thanks,

    Mike
  10. Zarko
    Admin
    Zarko avatar
    755 posts

    Posted 11 Dec 2014 Link to this post

    Hello Michael,
    Thank you for the clarifications - it really seems that a custom Command (and KeyBinding maybe) will be the better way to do this. The advantage of this approach is that your users will have the freedom to choose when they want to collapse the connections.
    If you need further assistance feel free to ask.

    Regards,
    Zarko
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
Back to Top
DevCraft banner