TreeLayout does not work for custom connectors

13 posts, 1 answers
  1. Kristoffer
    Kristoffer avatar
    158 posts
    Member since:
    Dec 2012

    Posted 14 Jan 2013 Link to this post

    I have a custom connection class as shown below. I have removed the 5 connectors of my nodes ("Auto", "Left", "Right", "Top", "Bottom") and added my own connectors "In" and "Out".

    public class MyChartConnection : RadDiagramConnection
    {
        public MyChartConnection(MyLink link)
            : base()
        {
            SourceConnectorPosition = /*ConnectorPosition.Auto*/ "in";
            SourceCapType = link.SourceCapType;

            TargetConnectorPosition = /*ConnectorPosition.Auto*/ "out";
            TargetCapType = link.TargetCapType;
        }
    }

    This crashes when I try to apply your TreeLayout(). Apparently, it cannot find the "Bottom" connector... Should I use another layout class? Do I have to implement my own layout class?

  2. Francois
    Admin
    Francois avatar
    10 posts

    Posted 15 Jan 2013 Link to this post

    Kristoffer,

    this is the same bug as the one which was recorded in PITS and has been resolved on January 9th.
    I have a working example with the current codebase but I reckon you'll have to wait till Q1.2013 is out.

    Sorry for this.

    All the best,
    Francois
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  3. UI for WPF is Visual Studio 2017 Ready
  4. Kristoffer
    Kristoffer avatar
    158 posts
    Member since:
    Dec 2012

    Posted 28 Jan 2013 Link to this post

    Just replaced my Telerik binaries with files from RadControls_for_WPF_2012_3_1314_DEV_hotfix.zip
    Same problem!


    ---------------------------

    ---------------------------
    System.Exception: Connector 'Bottom' does not exist.

       at Telerik.Windows.Controls.RadDiagramConnection.ResolveSourceConnector() in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Diagrams\Visuals\RadDiagramConnection.cs:line 955

       at Telerik.Windows.Controls.RadDiagramConnection.OnSourceConnectorPositionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Diagrams\Visuals\RadDiagramConnection.cs:line 902

       at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)

       at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)

       at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)

       at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)

       at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal)

       at System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value)

       at Telerik.Windows.Controls.RadDiagramConnection.set_SourceConnectorPosition(String value) in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Diagrams\Visuals\RadDiagramConnection.cs:line 352

       at Telerik.Windows.Diagrams.Core.OrgTreeRouter.DirectionalRouter.SetSourceAndTargetConnectors() in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Core\Routing\OrgTreeRouter.cs:line 93

       at Telerik.Windows.Diagrams.Core.OrgTreeRouter.TreeRouterBase.GetRoute(IConnection connection, Double connectionSpacing) in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Core\Routing\OrgTreeRouter.cs:line 332

       at Telerik.Windows.Diagrams.Core.OrgTreeRouter.GetRoutePoints(IConnection connection, Boolean showLastLine) in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Core\Routing\OrgTreeRouter.cs:line 66

       at Telerik.Windows.Diagrams.Core.RoutingService.BuildRoute(IConnection connection) in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Core\Services\RoutingService.cs:line 46

       at Telerik.Windows.Controls.Diagrams.GeometryFactory.CreateConnectionGeometry(IConnection connection, RoutingService routingService) in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Diagrams\Utilities\GeometryFactory.cs:line 346

       at Telerik.Windows.Controls.RadDiagramConnection.UpdateGeometryOverride() in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Diagrams\Visuals\RadDiagramConnection.cs:line 852

       at Telerik.Windows.Controls.RadDiagramConnection.Update(Boolean isManipulating) in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Diagrams\Visuals\RadDiagramConnection.cs:line 805

       at Telerik.Windows.Controls.RadDiagramConnection.Telerik.Windows.Diagrams.Core.IConnection.Update(Boolean isManipulating) in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Diagrams\Visuals\RadDiagramConnection.cs:line 525

       at Telerik.Windows.Diagrams.Core.GraphController.UpdateConnectionsAndCheckForSelection(IShape shape) in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Core\Controllers\GraphController.cs:line 707

       at Telerik.Windows.Diagrams.Core.GraphController.OnShapePropertyChanged(Object sender, PropertyEventArgs e) in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Core\Controllers\GraphController.Services.cs:line 422

       at Telerik.Windows.Controls.Diagrams.RadDiagramItem.OnPropertyChanged(String propertyName) in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Diagrams\Visuals\RadDiagramItem.cs:line 902

       at Telerik.Windows.Controls.Diagrams.RadDiagramItem.OnSizeChanged(Size newSize, Size oldSize) in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Diagrams\Visuals\RadDiagramItem.cs:line 992

       at Telerik.Windows.Controls.Diagrams.RadDiagramItem.DiagramItemSizeChanged(Object sender, SizeChangedEventArgs e) in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Diagrams\Visuals\RadDiagramItem.cs:line 1188

       at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)

       at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)

       at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)

       at System.Windows.FrameworkElement.OnRenderSizeChanged(SizeChangedInfo sizeInfo)

       at System.Windows.ContextLayoutManager.fireSizeChangedEvents()

       at System.Windows.ContextLayoutManager.UpdateLayout()

       at System.Windows.ContextLayoutManager.UpdateLayoutCallback(Object arg)

       at System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks()

       at System.Windows.Media.MediaContext.RenderMessageHandlerCore(Object resizedCompositionTarget)

       at System.Windows.Media.MediaContext.RenderMessageHandler(Object resizedCompositionTarget)

       at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)

       at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
    ---------------------------
    OK  
    ---------------------------



    And when trying to create a manual connection I now get the error below. The only way to get rid of the errors is to leave the original connectors... 

    ---------------------------

    ---------------------------
    System.ArgumentException: No neighour corners found!

       at Telerik.Windows.Diagrams.Core.InflatedRectRouter.GetNeighborCorners(String orientation, Rect rect, Point& n1, Point& n2) in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Core\Routing\InflatedRectRouter.cs:line 521

       at Telerik.Windows.Diagrams.Core.InflatedRectRouter.GetNearestNeighborSource(ConnectorInfo source, Point endPoint, Rect rectSource, Rect rectSink, Boolean& flag) in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Core\Routing\InflatedRectRouter.cs:line 355

       at Telerik.Windows.Diagrams.Core.InflatedRectRouter.GetRoutePoints(ConnectorInfo source, ConnectorInfo target, Boolean showLastLine) in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Core\Routing\InflatedRectRouter.cs:line 64

       at Telerik.Windows.Diagrams.Core.InflatedRectRouter.GetRoutePoints(IConnection connection, Boolean showLastLine) in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Core\Routing\InflatedRectRouter.cs:line 271

       at Telerik.Windows.Diagrams.Core.RoutingService.BuildRoute(IConnection connection) in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Core\Services\RoutingService.cs:line 50

       at Telerik.Windows.Controls.Diagrams.GeometryFactory.CreateConnectionGeometry(IConnection connection, RoutingService routingService) in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Diagrams\Utilities\GeometryFactory.cs:line 346

       at Telerik.Windows.Controls.RadDiagramConnection.UpdateGeometryOverride() in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Diagrams\Visuals\RadDiagramConnection.cs:line 852

       at Telerik.Windows.Controls.RadDiagramConnection.Update(Boolean isManipulating) in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Diagrams\Visuals\RadDiagramConnection.cs:line 805

       at Telerik.Windows.Controls.RadDiagramConnection.Telerik.Windows.Diagrams.Core.IConnection.Update(Boolean isManipulating) in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Diagrams\Visuals\RadDiagramConnection.cs:line 525

       at Telerik.Windows.Diagrams.Core.GraphController.OnConnectionPropertyChanged(Object sender, PropertyEventArgs e) in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Core\Controllers\GraphController.Services.cs:line 349

       at System.EventHandler`1.Invoke(Object sender, TEventArgs e)

       at Telerik.Windows.Controls.Diagrams.RadDiagramItem.OnPropertyChanged(String propertyName) in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Diagrams\Visuals\RadDiagramItem.cs:line 902

       at Telerik.Windows.Controls.RadDiagramConnection.set_EndPoint(Point value) in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Diagrams\Visuals\RadDiagramConnection.cs:line 340

       at Telerik.Windows.Diagrams.Core.ConnectionTool.MouseMove(PointerArgs e) in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Core\Tools\ConnectionTool.cs:line 89

       at Telerik.Windows.Diagrams.Core.ToolService.<>c__DisplayClassc.<MouseMove>b__b(IMouseListener tool) in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Core\Tools\ToolService.cs:line 142

       at System.Linq.Enumerable.Any[TSource](IEnumerable`1 source, Func`2 predicate)

       at Telerik.Windows.Diagrams.Core.ToolService.MouseMove(PointerArgs e) in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Core\Tools\ToolService.cs:line 142

       at Telerik.Windows.Diagrams.Core.GraphController.MouseMove(PointerArgs e) in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Core\Controllers\GraphController.cs:line 198

       at Telerik.Windows.Controls.RadDiagram.OnMouseMove(MouseEventArgs e) in c:\TB\117\WPF_Scrum\Current_HotFix\Sources\Diagrams\Diagrams\RadDiagram.cs:line 381

       at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)

       at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)

       at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)

       at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)

       at System.Windows.Input.InputManager.ProcessStagingArea()

       at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)

       at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)

       at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)

       at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)

       at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)

       at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)

       at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)

       at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
    ---------------------------
    OK  
    ---------------------------

  5. Kristoffer
    Kristoffer avatar
    158 posts
    Member since:
    Dec 2012

    Posted 28 Jan 2013 Link to this post

    RadControls_for_WPF_2012_3_1321_DEV_hotfix.zip - same problem.

    Please fix this as soon as possible! This is pretty much a blocker for us.
  6. Petar Mladenov
    Admin
    Petar Mladenov avatar
    2891 posts

    Posted 31 Jan 2013 Link to this post

    Hi Kristoffer,

     This bug is fixed but it won't be included in our internal builds. It will be included in the upcoming Official Q1 Release is mid-February. This mainly because it must go through our testing procedures successfully. On the other hand, we have missed to schedule it for Q1 in PITS, please excuse us for the inconvenience caused.

    Kind regards,
    Petar Mladenov
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  7. Kristoffer
    Kristoffer avatar
    158 posts
    Member since:
    Dec 2012

    Posted 02 Sep 2013 Link to this post

    Though this particular issue was solved, the TreeLayout algorithm still suffers when using custom connectors. More specifically, it often swaps the y-position of the parent with its child. This always fails:

    1) Add node A.
    2) Add node B.
    3) Not needed, but here for clarity: Rearrange the nodes so that B is above A.
    4) Connect from B's bottom connector to A's top connector.
    5) The nodes exchange positions, resulting in the attached image. (A is above B.)

    Do you rely on ZIndex or some other weird variable when arranging the nodes? I believe this bug is the root of all problems we see when laying out our nodes.
  8. Petar Mladenov
    Admin
    Petar Mladenov avatar
    2891 posts

    Posted 04 Sep 2013 Link to this post

    Hi Kristoffer,

    Could you please confirm that these provided steps are independent from scenarios where some shapes have multiple parents ? Several months ago you needed some kind of topological sorting and we explained that this currently cannot be achieved out of the box with TreeLayout and you will need custom Layout method or at least a method that works after the work of the TreeLayout (to arrange the additional parent nodes).
    If this is not the case could you please check out our test project where we are unable to reproduce similar issue. We delete a connection, then create manually new connections with mouse connecting custom connectors and the Layout does not replace the source and target shapes. Please let us know if we are missing anything in the attached sample.
    We do not rely on ZIndex when arranging the nodes. We use Position, Width, Height. And we also determine which node of the given two is the father, in tree with root - this is the one closer to the root.

    Regards,
    Petar Mladenov
    Telerik
    TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for WPF.
    Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
    Sign up for Free application insights >>
  9. Kristoffer
    Kristoffer avatar
    158 posts
    Member since:
    Dec 2012

    Posted 04 Sep 2013 Link to this post

    Thanks for your response. No, this error has nothing to do with multiple root nodes. The five steps were performed on a diagram with no shapes - hence no other root nodes.

    I'll try your sample project right away.
  10. Kristoffer
    Kristoffer avatar
    158 posts
    Member since:
    Dec 2012

    Posted 04 Sep 2013 Link to this post

    Yes, I can reproduce the error in your sample. Hooray!! :D

    1) Copy a node (Ctrl+C).
    2) Remove all nodes (Ctrl+A, Del).
    3) Paste node #1 (Ctrl+V).
    4) Paste node #2 (Ctrl+V).
    5) Move node #2 above node #1.
    6) Connect them.
    7) Press "Layout".

    Voilà!
  11. Answer
    Petar Mladenov
    Admin
    Petar Mladenov avatar
    2891 posts

    Posted 04 Sep 2013 Link to this post

    Hello Kristoffer,

     The Layout Button invokes the function PrepareAndLayout:

    private void PrepareAndLayout()
    {          
        TreeLayoutSettings settings = new TreeLayoutSettings()
        {
            TreeLayoutType = TreeLayoutType.TreeDown,
            VerticalDistance = 100,
            UnderneathHorizontalOffset = 50,
            UnderneathVerticalTopOffset = 50,
            UnderneathVerticalSeparation = 60
        };
        settings.Roots.Add(this.diagram.Shapes[0]);
        OrgTreeRouter router = new OrgTreeRouter()
        {
            TreeLayoutType = TreeLayoutType.TreeDown,
            ConnectionOuterSpacing = 20,
        };
        this.diagram.RoutingService.Router = router;
        this.diagram.Layout(LayoutType.Tree, settings);
    }
    You can see the green line sets the first shape in the Diagram.Shapes collection as the root of the tree which will be arranged. So it is entirely expected that the first pasted node will be set on top of the second pasted after layout. The first pasted becomes the first in the Shapes colelction.

    Regards,
    Petar Mladenov
    Telerik
    TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for WPF.
    Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
    Sign up for Free application insights >>
  12. Kristoffer
    Kristoffer avatar
    158 posts
    Member since:
    Dec 2012

    Posted 04 Sep 2013 Link to this post

    We don't add any shapes to the Roots collection. Does it pick an arbitrary (e.g. first created) node in that case?
  13. Petar Mladenov
    Admin
    Petar Mladenov avatar
    2891 posts

    Posted 04 Sep 2013 Link to this post

    Hello Kristoffer,

     No, when there is no root set, the algorithm finds a root on the basis of longest paths in the graph:

    /// <summary>
        /// Attempts to find a tree root by looking at the longest paths in the graph.
        /// </summary>
        /// <remarks>The algorithms looks for all shortest paths between all vertices, which means it will also function for disconnected graphs but will return the root
        /// of the tree with longest path.</remarks>
        /// <returns>A tree root or <c>null</c> is none was found.
        /// </returns>
        public TNode FindTreeRoot()
        {
    However, in order to avoid roots you do not wish, simply set the Roots in the TreeViewSettings.

    Regards,
    Petar Mladenov
    Telerik
    TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for WPF.
    Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
    Sign up for Free application insights >>
  14. Kristoffer
    Kristoffer avatar
    158 posts
    Member since:
    Dec 2012

    Posted 04 Sep 2013 Link to this post

    Thanks!

    Adding all nodes that have no connections from above (i.e. input connectors are either not present or have no connections) solved the issue.
Back to Top
UI for WPF is Visual Studio 2017 Ready