FlexChart | ComponentOne
TreeMap / Data Binding
In This Topic
    Data Binding
    In This Topic

    The TreeMap chart control binds to hierarchical data, to represent the elements of tree-like data as nested rectangles. Once the control binds to the data source and displays data items as rectangles, the size and color of these constituting rectangles enable analysis and comparison of data items.

    FlexChartBase class exposes ItemsSource property, which takes collection of the objects, that contain data, to populate in tree map chart. The Binding and BindingName properties are instrumental in generating rectangular nodes for data items and their respective categories or groups. While Binding property takes string value depicting the name of the property of data item that contains numeric data value, helpful in calculating the size of rectangular nodes, BindingName takes string value depicting the name of data items. ChildItemPath property ensures that a hierarchical structure of the provided data collection is maintained, by communicating to the control about the child items within the data.

    To elaborate how data is populated in a tree map chart, let’s consider a use case where we try to compare yearly sales (in units sold) of a multi-brand retail store. The analysis can then further be drilled down to quarters in a year and then to months in a quarter, by using Treemap chart. Here yearly sales are represented by the top level rectangles, quarterly sales in those years represent the subsequent level, and monthly sales form the next level that is leaf nodes in tree map.

    The following image illustrates sales in a retail store, in terms of units sold, through TreeMap chart control. Note that the image shows hierarchical data up to third level, that is months in respective quarters of the years.

    TreeMap comparing sales

    Back to Top

    In this example, data generated in DataService class is serving as the source for tree map chart.

    1. Create a hierarchical data source
      1. In the code view, create a DataService class to generate hierarchical data, as shown in the following code.
        Public Class DataService
            Private rnd As New Random()
            Shared _default As DataService
        
            Public Shared ReadOnly Property Instance() As DataService
                Get
                    If _default Is Nothing Then
                        _default = New DataService()
                    End If
        
                    Return _default
                End Get
            End Property
        
            Public Shared Function CreateHierarchicalData() As List(Of DataItem)
                Dim rnd As Random = Instance.rnd
        
                Dim years As New List(Of String)()
                Dim times As New List(Of List(Of String))() From {
                    New List(Of String)() From {
                        "Jan",
                        "Feb",
                        "Mar"
                    },
                    New List(Of String)() From {
                        "Apr",
                        "May",
                        "June"
                    },
                    New List(Of String)() From {
                        "Jul",
                        "Aug",
                        "Sep"
                    },
                    New List(Of String)() From {
                        "Oct",
                        "Nov",
                        "Dec"
                    }
                }
        
                Dim items As New List(Of DataItem)()
                Dim yearLen = Math.Max(CInt(Math.Round(Math.Abs(5 - Instance.rnd.NextDouble() * 10))), 3)
                Dim currentYear As Integer = DateTime.Now.Year
                For i As Integer = yearLen To 1 Step -1
                    years.Add((currentYear - i).ToString())
                Next
                Dim quarterAdded = False
        
                years.ForEach(Function(y)
                                  Dim i = years.IndexOf(y)
                                  Dim addQuarter = Instance.rnd.NextDouble() > 0.5
                                  If Not quarterAdded AndAlso i = years.Count - 1 Then
                                      addQuarter = True
                                  End If
                                  Dim year = New DataItem() With {
                                      .Year = y
                                  }
                                  If addQuarter Then
                                      quarterAdded = True
                                      times.ForEach(Function(q)
                                                        Dim addMonth = Instance.rnd.NextDouble() > 0.5
                                                        Dim idx As Integer = times.IndexOf(q)
                                                        Dim quar As String
                                                        quar = "Q" + (idx + 1).ToString
                                                        Dim quarters = New DataItem() With {
                                                            .Year = y,
                                                            .Quarter = quar
                                                        }
                                                        If addMonth Then
                                                            q.ForEach(Function(m)
                                                                          quarters.Items.Add(New DataItem() With {
                                                                              .Year = y,
                                                                              .Quarter = quar,
                                                                              .Month = m,
                                                                              .Value = rnd.[Next](20, 30)
                                                                          })
        
                                                                      End Function)
                                                        Else
                                                            quarters.Value = rnd.[Next](80, 100)
                                                        End If
                                                        year.Items.Add(quarters)
        
                                                    End Function)
                                  Else
                                      year.Value = rnd.[Next](80, 100)
                                  End If
                                  items.Add(year)
        
                              End Function)
        
                Return items
            End Function
        
        End Class
        
        public class DataService
        {
            Random rnd = new Random();
            static DataService _default;
        
            public static DataService Instance
            {
                get
                {
                    if (_default == null)
                    {
                        _default = new DataService();
                    }
        
                    return _default;
                }
            }      
        
            public static List<DataItem> CreateHierarchicalData()
            {
                Random rnd = Instance.rnd;
        
                List<string> years = new List<string>();
                List<List<string>> times = new List<List<string>>()
                {
                    new List<string>() { "Jan", "Feb", "Mar"},
                    new List<string>() { "Apr", "May", "June"},
                    new List<string>() { "Jul", "Aug", "Sep"},
                    new List<string>() { "Oct", "Nov", "Dec" }
                };
        
                List<DataItem> items = new List<DataItem>();
                var yearLen = Math.Max((int)Math.Round(Math.Abs(5 - Instance.rnd.NextDouble() * 10)), 3);
                int currentYear = DateTime.Now.Year;
                for (int i = yearLen; i > 0; i--)
                {
                    years.Add((currentYear - i).ToString());
                }
                var quarterAdded = false;
        
                years.ForEach(y =>
                {
                    var i = years.IndexOf(y);
                    var addQuarter = Instance.rnd.NextDouble() > 0.5;
                    if (!quarterAdded && i == years.Count - 1)
                    {
                        addQuarter = true;
                    }
                    var year = new DataItem() { Year = y };
                    if (addQuarter)
                    {
                        quarterAdded = true;
                        times.ForEach(q =>
                        {
                            var addMonth = Instance.rnd.NextDouble() > 0.5;
                            int idx = times.IndexOf(q);
                            var quar = "Q" + (idx + 1);
                            var quarters = new DataItem() { Year = y, Quarter = quar };
                            if (addMonth)
                            {
                                q.ForEach(m =>
                                {
                                    quarters.Items.Add(new DataItem()
                                    {
                                        Year = y,
                                        Quarter = quar,
                                        Month = m,
                                        Value = rnd.Next(20, 30)
                                    });
                                });
                            }
                            else
                            {
                                quarters.Value = rnd.Next(80, 100);
                            }
                            year.Items.Add(quarters);
                        });
                    }
                    else
                    {
                        year.Value = rnd.Next(80, 100);
                    }
                    items.Add(year);
                });
        
                return items;
            }
        
        }
        
      2. Create a DataItem class to define list of objects to represent data items and their categories.
        Public Class DataItem
            Private _items As List(Of DataItem)
        
            Public Property Year() As String
                Get
                    Return m_Year
                End Get
                Set
                    m_Year = Value
                End Set
            End Property
            Private m_Year As String
            Public Property Quarter() As String
                Get
                    Return m_Quarter
                End Get
                Set
                    m_Quarter = Value
                End Set
            End Property
            Private m_Quarter As String
            Public Property Month() As String
                Get
                    Return m_Month
                End Get
                Set
                    m_Month = Value
                End Set
            End Property
            Private m_Month As String
            Public Property Value() As Double
                Get
                    Return m_Value
                End Get
                Set
                    m_Value = Value
                End Set
            End Property
            Private m_Value As Double
            Public ReadOnly Property Items() As List(Of DataItem)
                Get
                    If _items Is Nothing Then
                        _items = New List(Of DataItem)()
                    End If
        
                    Return _items
                End Get
            End Property
        End Class
        
        public class DataItem
        {
            List<DataItem> _items;
        
            public string Year { get; set; }
            public string Quarter { get; set; }
            public string Month { get; set; }
            public double Value { get; set; }
            public List<DataItem> Items
            {
                get
                {
                    if (_items == null)
                    {
                        _items = new List<DataItem>();
                    }
        
                    return _items;
                }
            }
        }
        

      Back to Top

    2. Bind TreeMap to the data source       


      To bind the TreeMap control to the data source use the following code.

      XAML
      Copy Code
          <Window
              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
              xmlns:local="clr-namespace:WpfTreeMapCS"
              xmlns:c1="http://schemas.componentone.com/winfx/2006/xaml"
              x:Class="WpfTreeMapCS.DataBinding"
              DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}"
              mc:Ignorable="d"
              Title="DataBinding" Height="300" Width="300">
          <Grid>
              <Grid.DataContext>
                  <local:TreeMapViewModel />
              </Grid.DataContext>
              <c1:C1TreeMap Binding="Value" 
                            BindingName="Year,Quarter,Month" 
                            ChildItemsPath="Items" 
                            ItemsSource="{Binding HierarchicalData}"
                            MaxDepth="3">
                  <c1:C1TreeMap.DataLabel>
                      <c1:DataLabel Content="{}{name}"                              
                                    Position="Center">
                          <c1:DataLabel.Style>
                              <c1:ChartStyle/>
                          </c1:DataLabel.Style>
                      </c1:DataLabel>
                  </c1:C1TreeMap.DataLabel>            
              </c1:C1TreeMap>
          </Grid>
      </Window>
      

      Back to Top

      Public Class TreeMapViewModel
          Public ReadOnly Property HierarchicalData() As List(Of DataItem)
              Get
                  Return DataService.CreateHierarchicalData()
              End Get
          End Property
      End Class
      
      public class TreeMapViewModel
      {
          public List<DataItem> HierarchicalData
          {
              get
              {
                  return DataService.CreateHierarchicalData();
              }
          }
      }
      
    3. Build and run the project
      1. Click Build | Build Solution to build the project.
      2. Press F5 to run the project.

      Back to Top

    See Also