How to draw a bar chart in SilverLight?

Asked By Eswaran Radhakrishnan
13-Nov-08 10:56 PM
Earn up to 0 extra points for answering this tough question.

Hi all,

How to draw a bar chart in silver Light the values should be taken from an xml file.? I need to know the what are the steps to follow for that.

It's very urgent.

Thanks

 R Eswaran

  re

Web Star replied to Eswaran Radhakrishnan
13-Nov-08 11:12 PM
   There are three steps to create the control:
  • Load the data from a .XAML
  • Initialize the needed components
  • Set their properties so that they arrange according to the size of the control.

Each time the control is resized we only perform the last step. But if you want to load new data after you loaded some you will have to initialize the control as a new. 

We perform the last two steps separately for the two distinguishing objects:

  • Chart
  • Legend

For the chart andthe legend we have a structure that contains all their components. 

The control is built using a few classes that extend framework classes:
Bar, BarGroup, MovableCanvas, MovableFramedCanvas. Let’s take a look at them. 

Bar – extendedCanvas with additionalTextBlock value centered on top of it.

 

public class Bar: Canvas
{
private TextBlock value;

public Bar():base()
{

    value = new TextBlock();
    this.Children.Add( value );
}

private void Refresh()
{
    value.SetValue( TopProperty, - value.ActualHeight );
    value.SetValue( LeftProperty, this.Width / 2 - value.ActualWidth / 2 );
}
 

public double ValueFontSize
{
    get { return value.FontSize; }
    set { this.value.FontSize = value; Refresh(); }
}
 

public String Value
{
    get { return this.value.Text; }
    set { this.value.Text = value; Refresh(); }
}
 

public new virtual double Width
{
    get { return base.Width; }
    set{ base.Width = value; Refresh(); }
}

public new virtual double Height
{
    get { return base.Height; }
    set { base.Height = value; Refresh(); }
}
}

 

BarGroup – a list of Bar objects that are contained in a Canvas, with an additional TextBlock centered under the canvas. This class is not a great example of OOP but is good enough to save some writing so we use it anyway. Think of it as a list of Bar objects, but arranged in a Canvas. HereRefresh()distributes the bars in the main canvas leaving some space(margin) in the left and right end, and no space between them:

 

    public class BarGroup: Canvas
    {
        private System.Collections.Generic.List<Bar> bar = new System.Collections.Generic.List<Bar>();
        private double margin;
        private double fontSizeCoefficient = 0.33;
        private TextBlock label = new TextBlock();
        public BarGroup(){…}
        public void RemoveBar( int index )
        public void AddBar( double height, String text )
        private void InitializeColors()
        public String Label
        public double Margin
        public double Count
        public new double Width
        public new double Height
        public Bar this[ int index ]   // Indexer declaration
        {
            get
            {
                // Check the index limits.
                if ( index < 0 || index >= bar.Count )
                    return null;
                else
                    return bar[ index ];
            }
        }

        private void Refresh()
        {
            double w = ( this.Width - 2 * margin ) / bar.Count;
            label.FontSize = Math.Pow( w * w, fontSizeCoefficient );
            for ( int count = bar.Count, i = 0 ; i < count ; i++ )
            {
                bar[ i ].Width = w;
                bar[ i ].ValueFontSize = Math.Pow( w * w, fontSizeCoefficient );
                bar[ i ].SetValue( Canvas.TopProperty, this.Height - bar[ i ].Height );
                bar[ i ].SetValue( Canvas.LeftProperty, margin + w * i );
                bar[ i ].SetValue( Canvas.TagProperty, margin + w * i );
            }
        }

        private void AlignLabel()
        {
                label.SetValue( Canvas.TopProperty, this.Height );
                label.SetValue( Canvas.LeftProperty, ( this.Width - label.ActualWidth ) / 2 );
        }
    }

 

MovableCanvas utilizes the mouse events to easily create, as because its name explains, a movable canvas. As you can see in the second part of the figure we add the change of mouse position to the canvas coordinates.

 

public class MovableCanvas: Canvas
{
    private Point draggingStartPoint = new Point();
    private bool isDragging = false;
    public MovableCanvas()
    {
            this.MouseLeftButtonDown += new MouseEventHandler( MoveableFrameCanvas_MouseLeftButtonDown );
            this.MouseMove +=
                new
MouseEventHandler( MoveableFrameCanvas_MouseMove );
            this.MouseLeftButtonUp += new MouseEventHandler( MoveableFrameCanvas_MouseLeftButtonUp );
    }

. . .

void MoveableFrameCanvas_MouseMove( object sender, MouseEventArgs e )
{
    if ( isDragging )
    {
        Canvas o = sender as Canvas;
        if ( o != null )
        {
        o.SetValue( Canvas.LeftProperty,
            ( double )o.GetValue( Canvas.LeftProperty ) + e.GetPosition( ( System.Windows.UIElement )this.Parent ).X - draggingStartPoint.X );
        o.SetValue( Canvas.TopProperty,
            ( double )o.GetValue( Canvas.TopProperty ) + e.GetPosition( ( System.Windows.UIElement )this.Parent ).Y - draggingStartPoint.Y );
 

        draggingStartPoint =
            e.GetPosition( ( System.Windows.UIElement )this.Parent );
        }
        else
            throw new NullReferenceException();
    }
}

 

MovableFramedCanvas – simply adds four lines in the ends of its canvas.

We use MovableFramedCanvas as foundation for the legend and chart.

 

public class MovableFramedCanvas: MovableCanvas
{
    Line[] frame = new Line[ 4 ];
    Color frameColor;
    double frameThickness;

    public MovableFramedCanvas()
    {
        for ( int i = 0 ; i < 4 ; i++ )
        {
            frame[ i ] = new Line();
            this.Children.Add( frame[ i ] );
        }

        frame[ 0 ].X1 = -5;
        frame[ 1 ].X1 = -5;
        frame[ 2 ].Y1 = -5;
        frame[ 3 ].Y1 = -5;
    }

    private void AdjustFrameHeight()
    {
        frame[ 1 ].Y1 = this.Height;
        frame[ 1 ].Y2 = this.Height;
        frame[ 2 ].Y2 = this.Height + 5;
        frame[ 3 ].Y2 = this.Height + 5;
    }

    private void AdjustFrameWidth()
    {
        frame[ 0 ].X2 = this.Width + 5;
        frame[ 1 ].X2 = this.Width + 5;
        frame[ 3 ].X1 = this.Width;
        frame[ 3 ].X2 = this.Width;
    }
 
}

Here is a visual explaination for some of the variаbles in the project.

 

Legend

Our legend is actually a MovableFramedCanvas with the colors and their meanings added to it as child elements. For clarity let’s name the pair color and text (corresponding to a bar) to be a label. Then they are named labelCanvas and labelText respectively. Those three elements are grouped into the structure named LEGEND.  

  also read this is good for barchart

Web Star replied to Eswaran Radhakrishnan
13-Nov-08 11:14 PM

  See this

Sagar P replied to Eswaran Radhakrishnan
13-Nov-08 11:18 PM
  Re :: Draw a bar chart in Silverlight
Shailendrasinh Parmar replied to Eswaran Radhakrishnan
13-Nov-08 11:32 PM

Hi,

 

Silverlight 2 Charts : Building Charts using Silverlight 2 Toolkit

Another milestone in Silverlight journey, Release of excellent Toolkit for Silverlight on Codeplex, to know more about it, do visit at :

http://www.codeplex.com/Silverlight

There are few new controls added to the Silverlight Arena as :

    • AutoCompleteBox
    • ButtonSpinner
    • Chart
    • DockPanel
    • Expander
    • HeaderedItemControl
    • HeaderedContentControl
    • ImplicitStyleManager
    • Label
    • NumericUpDown
    • TreeView
    • ViewBox
    • WrapPanel
    I guess rest are very much easy and some are familiar to Web Developers which are relevent to some of the controls in AJAX Control Toolkit e.g AutoCompleteBox,NumericUpDown etc.
    Silverlight Toolkit which exclusively supports Silverlight 2 RTW and easily installable too, To download the bits, you need to visit :

http://www.codeplex.com/Silverlight/Release/ProjectReleases.aspx?ReleaseId=18804

I personally recommend to copy all the DLL files from the Toolkit to C:\Program Files\Microsoft Silverlight\2.0.31005.0\..

This will ease to add to project as reference,and it will be like central repository of all main dll files.This is just for convenience.

Step 1 : Install Silverlight Toolkit by adding reference to DLLs inside Toolkit.

Process is very similar the way we implement for AJAX Control Toolkit, Once you do that successfully, All the controls will be available on Toolbox.

Step 2 : Implement LINQ to SQL to get data for Graph.

Step 3 : Write a Silverlight Enabled WCF service to fetch data.

For Step 2 & 3 , kindly follow my old article step-by-step :

http://pendsevikram.blogspot.com/2008/10/silverlight-2-grid-with-silverlight.html

and

http://pendsevikram.blogspot.com/2008/10/silverlight-2-grid-linq-to-sql.html

Step 4 : Configure the Chart Control and Bind it with Data.

Here I am showing first demo of Pie Chart with List<> [Collection] and then I will show it with service.

XAML Code :

<Grid x:Name="LayoutRoot" Background="White">
        <StackPanel>
            <charting:Chart Height="250" Width="400" Title="PUG –Silverlight Forum Monthly Activity" x:Name="MyPieChart" >
                <charting:Chart.Series>
                    <charting:PieSeries ItemsSource="{Binding}"
                                        IndependentValueBinding="{Binding ProductName}"
                                        DependentValueBinding="{Binding Sales                    </charting:PieSeries>
                </charting:Chart.Series>
            </charting:Chart></StackPanel>
   </Grid>

C# Code :

public partial class Page : UserControl
    {
        public Page()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(Page_Loaded);
        }

        void Page_Loaded(object sender, RoutedEventArgs e)
        {
            GetProductSales();
         }

        public void GetProductSales()
        {
            List<ProductSales> PieData = new List<ProductSales>();
            PieData.Add(new ProductSales() { ProductName = "Vikram Pendse", Sales = 10.5 });
            PieData.Add(new ProductSales() { ProductName = "Rashi Agarwal", Sales = 20.2 });
            PieData.Add(new ProductSales() { ProductName = "Prachi Oke", Sales = 30.2 });
            PieData.Add(new ProductSales() { ProductName = "Ekta Shetty", Sales = 40.1 });
            MyPieChart.DataContext = PieData;
            MyPieChart.LegendTitle = "User Activity on forums in %";
         }
    }

    public class ProductSales
    {
        public string ProductName { get; set; }
        public double Sales { get; set; }
    }

And output will be something like this :

SLPieUData

Next Step is to bind it with Service and this time I am using Bar charts along with Pie Chart.

XAML Code :

<Grid x:Name="LayoutRoot" Background="White">
        <StackPanel>
            <charting:Chart Height="250" Width="400" Title="ABC Ltd.- Q2 Business Development Report" x:Name="MyPieChart" >
                <charting:Chart.Series>
                   <charting:PieSeries ItemsSource="{Binding}"
                                        IndependentValueBinding="{Binding Salesperson}"
                                        DependentValueBinding="{Binding Percentage}" >
                    </charting:PieSeries>
                </charting:Chart.Series>
            </charting:Chart>
            <charting:Chart Height="250" Width="400" Title="ABC Ltd.- Q2 Business Development Report" x:Name="MyBarChart">
                <charting:Chart.Series>
                    <charting:ColumnSeries ItemsSource="{Binding}" Title="Sales"
                                        IndependentValueBinding="{Binding Salesperson}"
                                        DependentValueBinding="{Binding Percentage}" >
                    </charting:ColumnSeries>
                </charting:Chart.Series>
            </charting:Chart>
            </StackPanel>
    </Grid>

C# Code :

Service Code :

public class MySvc
    {
        [OperationContract]
        public List<MonthlySale> GetSalesData()
        {
            MyDatabaseDataContext db = new MyDatabaseDataContext();
            var temp = from sales in db.MonthlySales
                       where sales.Salesperson.Length > 0
                       select sales;
            return temp.ToList();
        }

    }

[Note : I have created a Table MonthlySales in Northwind Database for testing purpose.]

C# Code with Proxy of the Service after consumption :

public partial class Page : UserControl
   {
       public Page()
       {
           InitializeComponent();
           this.Loaded += new RoutedEventHandler(Page_Loaded);
       }

       void Page_Loaded(object sender, RoutedEventArgs e)
       {
           Proxy.MySvcClient svc = new Proxy.MySvcClient();
           svc.GetSalesDataCompleted += new EventHandler<SL_SilverlightToolkit.Proxy.GetSalesDataCompletedEventArgs>(svc_GetSalesDataCompleted);
           svc.GetSalesDataAsync();
       }

       void svc_GetSalesDataCompleted(object sender, SL_SilverlightToolkit.Proxy.GetSalesDataCompletedEventArgs e)
       {
           MyPieChart.DataContext = e.Result;
           MyPieChart.LegendTitle = "Business Generated in %";

           MyBarChart.DataContext = e.Result;
           MyBarChart.LegendTitle = "Business Generated in %";
       }

   }

And the result will look like :

SLFinalCharts

This is how we can implement Charts in Silverlight 2 using Silverlight Toolkit, Soon I will post more interesting demos in coming days with more and more controls and unique ideas, Hope this will help you to start doing development with Silverlight Toolkit.

 

Hope this helps.

  Re :: Draw a bar chart in Silverlight (Articles)
Shailendrasinh Parmar replied to Eswaran Radhakrishnan
13-Nov-08 11:35 PM

See the following forum discussion where you can find some more links to the articles

http://silverlight.net/forums/p/11364/53904.aspx

Hope it helps.

  Hi Sanjay Verma, I am getting error in ur code... Could you reply for that?
Eswaran Radhakrishnan replied to Shailendrasinh Parmar
14-Nov-08 05:39 AM

Hi Sanjay Verma,

I used ur code but I getting error in Xaml file. the error is displaying

<Grid x:Name="LayoutRoot" Background="White" >

<StackPanel>

<charting:Chart Height="250" Width="400" Title="ABC Ltd.- Q2 Business Development Report" x:Name="MyBarChart"> --------------> I am gettting error here

<charting:Chart.Series>

<charting:ColumnSeries ItemsSource="{Binding}" Title="Sales"

IndependentValueBinding="{Binding Salesperson}"

DependentValueBinding="{Binding Percentage}" >

</charting:ColumnSeries>

</charting:Chart.Series>

</charting:Chart>

</StackPanel>

</Grid>

Any Idea about that?

Thanks

R. Eswaran.

Create New Account