Skip to main content Skip to footer

Showing Master Detail data with C1Chart for WPF

There are situations when we need the chart to act as a drilldown data chart. For example, when we click on a data-point we need to show some more underlying data, associated with that point. The tooltip mechanism of C1Chart helps us to easily implement this scenario. The tooltip of C1Chart accepts an object and that is all we need to imeplement this. The object may be a datagrid, a list or even a chart. In this example, we talk about displaying the underlying data for a datapoint, in a C1Chart. Let’s start by creating a new WPF application inside Visual Studio. Then add two classes; Customer and Orders:

public class Orders  
 {  
    int _orderno;  
    double _orderlvalue;  
    string _customername;  
    public Orders(string customername, int orderno, double ordervalue)  
    {  
       _orderno = orderno;  
       _orderlvalue = ordervalue;  
       _customername = customername;  
    }  
    public int OrderNo  
    {  
       get { return _orderno; }  
       set { _orderno = value; }  
    }  
    public double OrderValue  
    {  
       get { return _orderlvalue; }  
       set { _orderlvalue = value; }  
    }  
    public string CustomerName  
    {  
       get { return _customername; }  
       set { _customername = value; }  
    }  
 }  

public class Customer  
 {  
    string _customername;  
    double _totalsales;  
    List<Orders> _customerorder;  

    public string CustomerName  
    {  
       get { return _customername; }  
       set { _customername = value; }  
    }  
    public double TotalSales  
    {  
       get { return _totalsales; }  
       set { _totalsales = value; }  
    }  
    public Customer(string customername, double totalsales)  
    {  
       _customername = customername;  
       _totalsales = totalsales;  
       _customerorder = new List<Orders>();  
    }  

    public List<Orders> CustomerOrder  
    {  
       get { return _customerorder; }  
       set { _customerorder = value; }  
    }  
 }

Now, add a C1Chart to the Main window. The is how XAML looks like:

 <Grid>  
           <c1:C1Chart Name="c1Chart1"  
                       Content=""  
                       ChartType="Column">  

                <TextBlock DockPanel.Dock="Top"  
                           Text="Master-Detail data with C1WPFChart"  
                           HorizontalAlignment="Center"  
                           Foreground="Blue"/>  

                <c1:C1Chart.Data>  
                    <c1:ChartData ItemNameBinding="{Binding Path=CustomerName}">  
                        <c1:DataSeries Label="TotalSales"  
                                       ValueBinding="{Binding Path=TotalSales}"  
                                       PlotElementLoaded="DataSeries_PlotElementLoaded"/>  
                    </c1:ChartData>  
                </c1:C1Chart.Data>  

                <c1:C1Chart.View>  
                    <c1:ChartView>  
                     <c1chart:ChartView.AxisY>  
                        <c1chart:Axis>  
                           <c1chart:Axis.Title>  
                              <TextBlock Text="Customer-TotalSales"  
                                         TextAlignment="Center"  
                                         Foreground="Blue"/>  
                           </c1chart:Axis.Title>  
                        </c1chart:Axis>  
                     </c1chart:ChartView.AxisY>  
                    </c1:ChartView>  
                </c1:C1Chart.View>  
        </c1:C1Chart>  
 </Grid>

Note that the chart dataseries is bound to “TotalValues” field of the Customer class and the “ItemNameBinding” is set to “CustomerName”. Next, we instantiate a list of “Customer “and add some data.

void LoadData()  
 {  
    _customers = new List<Customer>();  
    _orders = new List<Orders>();  

    _customers.Add(new Customer("ACorp", 5000));  

    Orders order1 = new Orders("ACorp", 1250, 2000);  
    Orders order2 = new Orders("ACorp", 1551, 1500);  
    Orders order3 = new Orders("ACorp", 1252, 1000);  
    Orders order4 = new Orders("ACorp", 1253, 500);  

    _customers[0].CustomerOrder.Add(order1);  
    _customers[0].CustomerOrder.Add(order2);  
    _customers[0].CustomerOrder.Add(order3);  
    _customers[0].CustomerOrder.Add(order4);  

    _customers.Add(new Customer("BCorp", 3000));  

    Orders order5 = new Orders("BCorp", 1331, 2000);  
    Orders order6 = new Orders("BCorp", 1332, 1000);  

    _customers[1].CustomerOrder.Add(order5);  
    _customers[1].CustomerOrder.Add(order6);  

    _customers.Add(new Customer("ABCorp", 7000));  

    Orders order7 = new Orders("ABCorp", 2441, 4000);  
    Orders order8 = new Orders("ABCorp", 2442, 3000);  

    _customers[2].CustomerOrder.Add(order7);  
    _customers[2].CustomerOrder.Add(order8);  

 }

Now, we create the chart that displays the underlying data for each datapoint, i.e. for each customer. When mouse is hovered over the “TotalSales” datapoint, this chart displays individual orders and their respective amounts.

Grid DetailChart(List<Customer> _lisorder, string customer)  
 {  
    C1.WPF.C1Chart.C1Chart _chart = null;  
    Grid _grid = null;  

    if (_chart != null)  
    {  
       _chart = null;  
    }  
    _chart = new C1.WPF.C1Chart.C1Chart();  
    _chart.Reset(true);  
    _chart.Width = 250;  
    _chart.Height = 150;  

    C1.WPF.C1Chart.DataSeries ds = new C1.WPF.C1Chart.DataSeries();  
    ds.Label = "Orders";  
    ds.ValueBinding = new Binding("OrderValue");  
    _chart.Data.ItemNameBinding = new Binding("OrderNo");  
    _chart.Data.Children.Add(ds);  

    var query = from q in _lisorder  
                where q.CustomerName==customer  
                select q.CustomerOrder;  

    _chart.Data.ItemsSource = query.ElementAt(0);  
    _chart.View.AxisX.Title = "Orders";  
    _chart.View.AxisY.Title = "Order Value";  
    _chart.Theme = c1Chart1.TryFindResource(new ComponentResourceKey(typeof(C1.WPF.C1Chart.C1Chart), "Office2007Blue")) as ResourceDictionary;  

    if (_grid != null)  
    {  
       _grid = null;  
    }  
    _grid = new Grid();  
    \_grid.Children.Add(\_chart);  
    return _grid;  
 }

The code (above )meets two objectives. Firstly, it creates a chart setting appropriate bindings by binding the chart to a LINQ query. This query filters out order data for a given customer. Then it binds the chart to the query. This shows how powerful LINQ is; we may provide different views to the user by generating runtime queries on a given collection. Secondly, it adds the chart to a layout grid which is the object that this function returns. Lastly, and the most important functionality, to implement is getting the customer names when mouse is hovered over a datapoint. To implement this, we add the following code in the PlotElementLoaded event of the main chart:

PlotElement pe = sender as PlotElement;  
        pe.MouseEnter += (send, ea) =>  
     {  
        c1Chart1.ToolTip = DetailChart(_customers, pe.DataPoint.Name);  
     };  

Using this code, we get the current PlotElement object. Thereafter, we set the tooltip of the chart to the object returned by the DetailChart function. We pass the _customers list and PlotElement datapoint name to the function as parameters. And yes, we haven't yet set the ItemSource of the main chart. Lets add the following code after InitializeComponent():

LoadData();  
 c1Chart1.Data.ItemsSource = _customers;  

And, we're all set. Run the application and hover the mouse over datapoint for “ACorp” customer and you get a detail-chart in the tooltip as shown in the following image: Download Sample

MESCIUS inc.

comments powered by Disqus