Skip to main content
All docs
V25.1
  • SankeyDiagramControl.LayoutAlgorithm Property

    Specifies Sankey layout algorithm settings.

    Namespace: DevExpress.XtraCharts.Sankey

    Assembly: DevExpress.XtraCharts.v25.1.UI.dll

    NuGet Package: DevExpress.Win.Charts

    Declaration

    public SankeyLayoutAlgorithmBase LayoutAlgorithm { get; set; }

    Property Value

    Type Description
    SankeyLayoutAlgorithmBase

    Contains Sankey layout algorithm settings.

    Remarks

    Linear Layout Algorithm

    You can use the predefined linear layout algorithm. Cast the LayoutAlgorithm property value to SankeyLinearLayoutAlgorithm to change default settings. Use the SankeyLinearLayoutAlgorithm.NodeAlignment property to specify the node alignment.

    The following example aligns nodes to the bottom of the SankeyDiagramControl:

    Sankey Node Alignment

    SankeyLinearLayoutAlgorithm layoutAlgorithm = (SankeyLinearLayoutAlgorithm)sankey.LayoutAlgorithm;
    layoutAlgorithm.NodeAlignment = SankeyNodeAlignment.Near;
    

    Custom Layout Algorithm

    To implement a custom layout, create a descendant of the SankeyLayoutAlgorithmBase class. Override the SankeyLayoutAlgorithmBase.CalculateNodeBounds method to specify node bounds:

    Custom Sankey layout algorithm

    using DevExpress.Charts.Sankey;
    using DevExpress.XtraCharts.Sankey;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    
    private void Form1_Load(object sender, EventArgs e) {
         SankeyDiagramControl sankeyDiagramControl1 = new SankeyDiagramControl();
         this.Controls.Add(sankeyDiagramControl1);
        List<SankeyItem> data = new List<SankeyItem> {
            new SankeyItem { Source = "France", Target = "UK", Value = 53 },
            new SankeyItem { Source = "Australia", Target = "UK", Value = 72 },
            new SankeyItem { Source = "France", Target = "Canada", Value = 81 },
            new SankeyItem { Source = "China", Target = "Canada", Value = 96 },
            new SankeyItem { Source = "UK", Target = "France", Value = 61 },
            new SankeyItem { Source = "Canada", Target = "France", Value = 89 } 
        };
        sankeyDiagramControl1.DataSource = data;
        sankeyDiagramControl1.SourceDataMember = "Source";
        sankeyDiagramControl1.TargetDataMember = "Target";
        sankeyDiagramControl1.WeightDataMember = "Value";
    
        sankeyDiagramControl1.LayoutAlgorithm = new MyLayoutAlgorithm();
        sankeyDiagramControl1.Width = 640;
        sankeyDiagramControl1.Height = 360;
    }
    
    public class SankeyItem {
        public string Source { get; set; }
        public string Target { get; set; }
        public double Value { get; set; }
    }
    public class MyLayoutAlgorithm : SankeyLayoutAlgorithmBase {
    
        void SpreadLevelIndex(ISankeyNodeLayoutItem node, int startingLevelIndex = 0) {
            node.LevelIndex = startingLevelIndex;
            if (node.OutputLinks == null)
                return;
            foreach (var outputLink in node.OutputLinks)
                SpreadLevelIndex(outputLink.Target, startingLevelIndex + 1);
        }
        public override void CalculateNodeBounds(IEnumerable<ISankeyNodeLayoutItem> nodes, DevExpress.Utils.DXRectangle bounds) {
            foreach (var node in nodes)
                if (node.InputLinks == null || node.InputLinks.Count == 0)
                    SpreadLevelIndex(node);
            int nodeWidth = bounds.Width / 10;
            int nodeHeight = bounds.Height / 10;
            int levelCount = nodes.Max(node => node.LevelIndex) + 1;
            int spaceBetweenLevels = (bounds.Width - nodeWidth) / (levelCount - 1);
            int maxNodeCountInALevel = nodes.GroupBy(node => node.LevelIndex).Max(group => group.Count());
            int spaceBetweenNodes = (bounds.Height - nodeHeight) / (maxNodeCountInALevel - 1);
            Dictionary<int, int> levelNodeCountPairs = new Dictionary<int, int>();
            foreach (var node in nodes) {
                if (!levelNodeCountPairs.TryGetValue(node.LevelIndex, out int nodeCount))
                    levelNodeCountPairs.Add(node.LevelIndex, 0);
                levelNodeCountPairs[node.LevelIndex]++;
                node.Bounds = new DevExpress.Utils.DXRectangle(bounds.Left + node.LevelIndex * spaceBetweenLevels, bounds.Top + nodeCount * spaceBetweenNodes, nodeWidth, nodeHeight);
            }
        }
    }
    
    See Also