Visifire Now Supports DataBinding

Sunil

Today we are releasing the much awaited DataBinding feature in Visifire 3.0.3 beta 3. Now you can Bind any DataSource at the Series level so that the Chart gets generated automatically and reflects any change. Below is a demonstration of DataBinding. You can change the Values in DataGrid and the Chart gets updated automatically.

Get Microsoft Silverlight

Here is the source code for the above sample. Also you can visit Visifire documentation here for more info.

You can download Visifire 3.0.3 beta 3 from our download page.

Cheers,
Team Visifire


Exporting Visifire Silverlight Chart as Image

Chirag

Exporting Silverlight charts to images has been the most coveted feature. In this tutorial, I am going to show you to export Visifire Silverlight chart as image from managed code. So before we start lets check out the live example below.

Get Microsoft Silverlight

Project Setup

Create a “Silverlight Application” project. Download the latest Visifire binaries from here. Extract the Zip file and add reference for the file named “SLVisifire.Charts.dll”. In this sample, I am going to use WriteableBitmap class in order to extract the pixel wise color information of the chart rendered inside Silverlight content. We will take help of JpegEncoder provided by a third party library called FJ.Core to encode the raster information to file stream.

Please download FJ.Core library from here and add the FJ.Core.dll as reference to the project.

Below are the steps that we are going to follow.

  1. Construct the Chart XAML inside MainPage.xaml.
  2. Exporting Chart as image.

Constructing Chart XAML

Open MainPage.xaml page, add a Chart and a button inside it as shown below:

<UserControl x:Class="SLSave2Image.MainPage"
    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:vc="clr-namespace:Visifire.Charts;assembly=SLVisifire.Charts"
    mc:Ignorable="d" Width="500" Height="480">
    <Grid x:Name="LayoutRoot">
        <StackPanel>
            <vc:Chart Name="MyChart" Width="500" Height="300" Theme="Theme1">

                <vc:Chart.Titles>
                    <vc:Title Text="Visifire Chart"/>
                </vc:Chart.Titles>

                <vc:Chart.Series>
                    <vc:DataSeries RenderAs="Column" LabelEnabled="True">
                        <vc:DataSeries.DataPoints>
                            <vc:DataPoint AxisXLabel="Jan" YValue="35"/>
                            <vc:DataPoint AxisXLabel="Feb" YValue="32"/>
                            <vc:DataPoint AxisXLabel="Mar" YValue="27"/>
                            <vc:DataPoint AxisXLabel="Apr" YValue="17"/>
                            <vc:DataPoint AxisXLabel="May" YValue="16"/>
                        </vc:DataSeries.DataPoints>
                    </vc:DataSeries>
                </vc:Chart.Series>
            </vc:Chart>
            <Button Name="ButtonSave" Height="25" Width="160" Content="Save Chart" ></Button>
        </StackPanel>
    </Grid>
</UserControl>

Exporting Chart as image

Now open MainPage.xaml.cs page and add the following namespaces.

using FluxJpeg.Core;
using FluxJpeg.Core.Encoder;
using System.Windows.Media.Imaging;
using System.IO;
using Visifire.Charts;

Now attach an event handler for Click event of Button inside the Page constructor.

public MainPage()
{
    InitializeComponent();

    ButtonSave.Click += new RoutedEventHandler(ButtonSave_Click);
}

void ButtonSave_Click(object sender, RoutedEventArgs e)
{
    SaveToImage(MyChart);
}

Inside the ButtonSave event handler declare a function called SaveToImage() which will accept Chart as parameter as shown above.

Now inside the function definition, create a WriteableBitmap out of a Chart and collect the raster information from it. Then encode the raster information to file stream using JpegEncoder present in FJ.Core library as shown below. Finally save the file stream as image into hard drive.

/// <summary>
/// Save Visifire chart as Image
/// </summary>
/// <param name="Chart">Visifire.Charts.Chart</param>
private void SaveToImage(Chart chart)
{
    try
    {
        WriteableBitmap bitmap = new WriteableBitmap(chart, null);

        if (bitmap != null)
        {
            SaveFileDialog saveDlg = new SaveFileDialog();
            saveDlg.Filter = "JPEG Files (*.jpeg)|*.jpeg";
            saveDlg.DefaultExt = ".jpeg";

            if ((bool)saveDlg.ShowDialog())
            {
                using (Stream fs = saveDlg.OpenFile())
                {
                    MemoryStream stream = GetImageStream(bitmap);

                    //Get Bytes from memory stream and write into IO stream
                    byte[] binaryData = new Byte[stream.Length];
                    long bytesRead = stream.Read(binaryData, 0, (int)stream.Length);
                    fs.Write(binaryData, 0, binaryData.Length);
                }
            }
        }
    }
    catch(Exception ex)
    {
        System.Diagnostics.Debug.WriteLine("Note: Please make sure that Height and Width of the chart is set properly.");
        System.Diagnostics.Debug.WriteLine(ex.Message);
    }
}

/// <summary>
/// Get image MemoryStream from WriteableBitmap
/// </summary>
/// <param name="bitmap">WriteableBitmap</param>
/// <returns>MemoryStream</returns>
public static MemoryStream GetImageStream(WriteableBitmap bitmap)
{
    byte[][,] raster = ReadRasterInformation(bitmap);
    return EncodeRasterInformationToStream(raster, ColorSpace.RGB);
} 

/// <summary>
/// Reads raster information from WriteableBitmap
/// </summary>
/// <param name="bitmap">WriteableBitmap</param>
/// <returns>Array of bytes</returns>
public static byte[][,] ReadRasterInformation(WriteableBitmap bitmap)
{
    int width = bitmap.PixelWidth;
    int height = bitmap.PixelHeight;
    int bands = 3;
    byte[][,] raster = new byte[bands][,];

    for (int i = 0; i < bands; i++)
    {
        raster[i] = new byte[width, height];
    }

    for (int row = 0; row < height; row++)
    {
        for (int column = 0; column < width; column++)
        {
            int pixel = bitmap.Pixels[width * row + column];
            raster[0][column, row] = (byte)(pixel >> 16);
            raster[1][column, row] = (byte)(pixel >> 8);
            raster[2][column, row] = (byte)pixel;
        }
    }

    return raster;
}

/// <summary>
/// Encode raster information to MemoryStream
/// </summary>
/// <param name="raster">Raster information (Array of bytes)</param>
/// <param name="colorSpace">ColorSpace used</param>
/// <returns>MemoryStream</returns>
public static MemoryStream EncodeRasterInformationToStream(byte[][,] raster, ColorSpace colorSpace)
{
    ColorModel model = new ColorModel { colorspace = ColorSpace.RGB };
    FluxJpeg.Core.Image img = new FluxJpeg.Core.Image(model, raster);

    //Encode the Image as a JPEG
    MemoryStream stream = new MemoryStream();
    FluxJpeg.Core.Encoder.JpegEncoder encoder = new FluxJpeg.Core.Encoder.JpegEncoder(img, 100, stream);
    encoder.Encode();

    // Back to the start
    stream.Seek(0, SeekOrigin.Begin);

    return stream;
}

You can download the complete solution here

(Hat tip to Visifire user Sagi Karni, Intel Corp)

Cheers,
Team Visifire


Step by step breakdown of Visifire rendering logic

Sunil

Introduction

Since the release of Visifire, we have got a lot of positive response from users on the simplicity, looks, customizability of Visifire over other Charting Controls in the market. What made it possible is, Visifire’s underlying set of algorithms that determine the best Visualization for a given set of parameters. So even when you provide bare minimum data required for rendering, Visifire renders a nice looking Chart which has tooltips, default interactivity like explode in Pie Chart, auto font-color for labels depending on the Chart Background color, auto indexing of DataPoints when XValue is not provided, etc.

Though Visifire makes effort to find the best visualization for any given case, its not always enough for all the applications. So we do have relevant properties for making it possible to customize according to individual needs. In this blog am going to explain the default rendering behavior of Visifire and how one can override them according to his needs.

1. Pictorial representation of Various elements/regions in a Chart

Silverlight Chart Control

2. A Minimal Chart

Below is a Minimal Chart and the XAML required to create it.

Img2

<vc:Chart xmlns:vc="clr-namespace:Visifire.Charts;assembly=SLVisifire.Charts"
          Width="500" Height="300">            
    <vc:Chart.Series>
 
        <vc:DataSeries>
            <vc:DataSeries.DataPoints>
                <vc:DataPoint YValue="207349" />
                <vc:DataPoint YValue="274316" />
                <vc:DataPoint YValue="318845" />
                <vc:DataPoint YValue="345254" />
                <vc:DataPoint YValue="351139" />
            </vc:DataSeries.DataPoints>
        </vc:DataSeries>
 
    </vc:Chart.Series>
</vc:Chart>

 

In the above XML we have defined YValue for all the DataPoints. When we look at the rendered chart, we can observe that the DataPoints have been numbered from 1 to 5. DataPoints are numbered automatically in the order of their appearance. If you want to override this default behavior, you can either set XValue for numbers or AxisXLabel in case you want to display string. Note that setting XValue will place DataPoints according to the position of XValue on X-Axis. Chart also shows ToolTip by default.

So by default the Chart adds

  1. XValue – index values
  2. ToolTip
  3. Comma for every thousandth digit on YAxis

3. Customizing Visifire

Chart in the previous section is Minimal in the sense we have not set any property required to customize the Chart. Below are few of the common stuff that you might want to add to the Chart.

  1. Title
  2. XValue/AxisXLabel for each DataPoint
  3. Prefix a symbol to the labels on YAxis – $ for example to make Label to look like $50,000
  4. Customize Values shown in the Tooltip

Below is how the Chart looks after customization

Img3

<vc:Chart xmlns:vc="clr-namespace:Visifire.Charts;assembly=SLVisifire.Charts"
           Width="500" Height="300">
     
     <vc:Chart.Titles>
         <vc:Title Text="Product Sales by Month"></vc:Title>    
     </vc:Chart.Titles>
     
     <vc:Chart.AxesY>
         <vc:Axis Prefix="$"></vc:Axis>
     </vc:Chart.AxesY>
     
     <vc:Chart.Series>
         <vc:DataSeries ToolTipText="#AxisXLabel, Y = #YValue">
             <vc:DataSeries.DataPoints>
                 <vc:DataPoint AxisXLabel="Jan" YValue="207349" />
                 <vc:DataPoint AxisXLabel="Feb" YValue="274316" />
                 <vc:DataPoint AxisXLabel="Mar" YValue="318845" />
                 <vc:DataPoint AxisXLabel="Apr" YValue="345254" />
                 <vc:DataPoint AxisXLabel="May" YValue="351139" />
             </vc:DataSeries.DataPoints>
         </vc:DataSeries>
     </vc:Chart.Series>
 </vc:Chart>

In the above example I’ve used AxisXLabel, as the Labels on the XAxis are strings. If the values are numeric, then you can use XValue. In case you set both the properties, then the DataPoints are placed according to XValue and XValues are replaced by AxisXLabels wherever available. Below is an example.

Img4

<vc:Chart xmlns:vc="clr-namespace:Visifire.Charts;assembly=SLVisifire.Charts"
          Width="500" Height="300">
    
    <vc:Chart.Series>
        <vc:DataSeries ToolTipText="#AxisXLabel, Y = #YValue">
            <vc:DataSeries.DataPoints>
                <vc:DataPoint XValue="1" YValue="207349" />
                <vc:DataPoint XValue="3" YValue="274316" />
                <vc:DataPoint XValue="4" YValue="318845" />
                <vc:DataPoint XValue="5" AxisXLabel="Five" YValue="345254" />
                <vc:DataPoint XValue="6" YValue="351139" />
            </vc:DataSeries.DataPoints>
        </vc:DataSeries>                
    </vc:Chart.Series>
 
</vc:Chart>

4. How the PlotArea width is calculated and how to control it

While allocating region for various elements in the Chart, PlotArea viewport width is determined at the end after allocating region for Title, Legend, AxisX, AxisY. So for example, if we place Legend to the right, then the viewport size reduces depending on the Legend Size. Below is an illustration.

Img5

You can see that the PlotArea "Viewport" width has reduced because of the Legend. But at the same time, the Actual PlotArea Size can extend further resulting in a ScrollBar. This can happen whenever ScrollingEnabled is set to true.

Through some trials, we have determined the relation between the DataPoint Width and Chart Size which makes the Chart to look good/readable and accordingly we are setting the PlotArea Width. Below is the algorithm.

If, ( Max Difference of XValues / Min Difference of XValues ) > MagicNumber, that means PlotArea width needs to be more than that of the viewport width – which results in ScrollBar. We found the equation for MagicNumber through trials with varying chart sizes and varying number of DataPoints. Below is how we calculate it.

MagicNumber = Current PlotArea width * 35 / 550

Now, PlotArea width can be calculated as below.

PlotArea width = ( Max Difference of XValues / Min Difference of XValues ) * 550 / 34

For multi series Column and Bar Charts, we need to multiply 550 with appropriate number of series that get rendered side by side.

5. How Datapoint width is calculated and how to control it

In case of Column and Bar Charts, DataPointWidth is determined based on the two closest DataPoints. Say, the XValues of 4 DataPoints are {1, 4, 5, 7, 9}, then the closest two DataPoints are 2nd and 3rd with difference in XValue of 1. So, in order to be able to draw both the DataPoints without overlap, we need to divide the available space between the two. As a result of which, Maximum Width of DataPoints will be equal to the minimum difference between XValues.

Now, we also need to give some spacing between the two DataPoints which is determined as .1 * ( Minimum Difference of XValues ). So, the DataPoint width finally comes down to .9 * ( Minimum Difference of XValues ) . In case the Chart is MultiSeries, then we need to place multiple columns within the same region. So, the column width calculated as above is divided by the number of series needed to be drawn.

Img6

Img7

In certain cases, the calculated width can go below 1px which will make Columns invisible. So, Visifire sets a lower limit of 2px to DataPoint width. You can also control the width of DataPoint by setting DataPointWidth property as a percentage of PlotArea ViewPort width. For example, setting the DataPointWidth to 5 will result in a Chart as below.

Img8

Please note that increasing/decreasing the Width of DataPoints will not change the relative position of DataPoints. So, if you increase the DataPointWidth over a certain range, columns will actually overlap. In the next section I’ll explain how you can overcome this limitation.

6. How Axis, Interval and AxisLabels work

Whenever you create a chart, by default Visifire tries to calculate the best possible Range and interval for Axis so that it is easier for the Humans to grasp/read. Human readable in the sense, it tries to make the interval a multiple of 1,2,5 or 10 and tries to keep the number of intervals around 8. So, whenever the interval is not 1, it might skip some of the AxisXLabel if you have defined.

Img10

<vc:DataSeries.DataPoints>
     <vc:DataPoint XValue="1" YValue="207349" />
     <vc:DataPoint XValue="3" YValue="274316" />
     <vc:DataPoint XValue="4" AxisXLabel="Four" YValue="318845" />
     <vc:DataPoint XValue="5" YValue="345254" />
     <vc:DataPoint XValue="6" YValue="351139" />
     <vc:DataPoint XValue="7" YValue="217349" />
     <vc:DataPoint XValue="9" YValue="224316" />
     <vc:DataPoint XValue="10" YValue="298845" />
     <vc:DataPoint XValue="11" YValue="335254" />
     <vc:DataPoint XValue="13" YValue="371139" />
 </vc:DataSeries.DataPoints>

Note that I’ve skipped all other elements apart from DataPoints collection just to keep the xaml compact. In the above example you can see that the interval is 2. So, if in case you set AxisXLabel for 3rd DataPoint, then it’ll not be shown. You can override this default behavior by setting the interval property of Axis to 1 as shown below.

Img11

<vc:Chart.AxesX>
    <vc:Axis Interval="1"></vc:Axis>
</vc:Chart.AxesX>
 
<vc:Chart.Series>
    <vc:DataSeries ToolTipText="#AxisXLabel, Y = #YValue">
        <vc:DataSeries.DataPoints>
            <vc:DataPoint XValue="1" YValue="207349" />
            <vc:DataPoint XValue="3" YValue="274316" />
            <vc:DataPoint XValue="4" AxisXLabel="Four" YValue="318845" />
            <vc:DataPoint XValue="5" YValue="345254" />
            <vc:DataPoint XValue="6" YValue="351139" />
            <vc:DataPoint XValue="7" YValue="217349" />
            <vc:DataPoint XValue="9" YValue="224316" />
            <vc:DataPoint XValue="10" YValue="298845" />
            <vc:DataPoint XValue="11" YValue="335254" />
            <vc:DataPoint XValue="13" YValue="371139" />
        </vc:DataSeries.DataPoints>
    </vc:DataSeries>          
</vc:Chart.Series>

While rendering the Axis, Visifire tries to automatically place AxisLabels in such a way that they don’t overlap. Say, if we change the AxisXLabel from "Four" to "XValue is Four", then it is obvious that the Label is long and it’ll overlap the neighboring AxisLabels. So, Visifire starts showing labels in 2 rows as shown below.

Img12

Now if we further increase the AxisXLabel to "DataPoint XValue is Four", then it becomes difficult to show Labels in two rows. So the next alternative will be to rotate the AxisLabel so that it doesn’t overlap the neighboring AxisXLabels.

Img13

You can customize Axis by setting Interval, MinimumValue, MaximumValue, etc as mentioned in the following document.

7. How Labels are placed

Below is an image showing Labels in Visifire. In order to show Label, one needs to enable them by setting LabelEnabled to True in DataSeries.

Img14

<vc:DataSeries LabelEnabled="True" ToolTipText="#AxisXLabel, Y = #YValue">
    <vc:DataSeries.DataPoints>
        <vc:DataPoint YValue="207349" />
        <vc:DataPoint YValue="274316" />
        <vc:DataPoint YValue="318845" />
        <vc:DataPoint LabelText="Label" YValue="345254" />
        <vc:DataPoint YValue="351139" />
        <vc:DataPoint YValue="217349" />
        <vc:DataPoint YValue="224316" />
        <vc:DataPoint YValue="298845" />
        <vc:DataPoint YValue="335254" />
        <vc:DataPoint YValue="371139" />                           
    </vc:DataSeries.DataPoints>
</vc:DataSeries>

See that Labels and AxisLabels are different. AxisLabel is one which is shown below the Axis and Labels are shows on/above the DataPoints.

You can observe that few of the Labels are outside the DataPoint and few are inside. Few have Black font color and few have White. Though the placement seems random at first place, it is not. Below I’ll explain the flow.

While placing Label for a DataPoint, Visifire first tries to place it horizonatally outside DataPoint. If the DataPoint width is more than the Label’s width, then Label is placed horizontally as in case of 4th DataPoint. If the DataPoint width is less than that of Label’s, then the Label is placed vertically. Now, whether the Label is placed on top of columns or inside the columns is determined by the availability of space outside the Column. If there is enough space outside the column, then the Labels are placed outside of DataPoint. If not, then the Labels are placed inside DataPoint.


Creating Silverlight Charts from SQL Data using ASP.Net and Visifire

vivek

Introduction

In this tutorial am going to show you how to pull SQL data and create a nice chart out of it using Visifire. It just takes few minutes!!

In order to create this sample, I chose Microsoft SQL Server Sample database Northwind.mdf. You can download it here.

Visifire is available in two flavors. One in the form of an assembly which you can use within Silverlight applications and another one packaged as .xap file which you can embed within any webpage. Am using the latter one.

Visifire requires the Data to be furnished in the form of XML through a JavaScript API (Visifire2.js). You can either pass an XML string or specify the URI where XML data is available. In this example am using the latter method. In order to understand the basic XML structure required by Visifire, you can refer the documentation.

Project Setup

Create an “ASP.Net Web Application” project and add a new folder “Visifire”. Download the latest Visifire binaries from here. Extract the Zip file and add two files named “SL.Visifire.Charts.xap” and “Visifire2.js” to the folder. Now, add NORTHWND.MDF file into App_Data folder in the solution.

Am using two aspx pages in this sample.

  1. Data.aspx – One which pull the Data from SQL and creates required XML structure out of it. Am using aspx page just to keep it simple.
  2. Default.aspx – Chart is embedded into this page.

solutionexplorer

Below are the steps that we are going to follow.

  1. Pull the SQL Data in Data.aspx.cs file.
  2. Construct the Data XML inside Data.aspx.cs and return.
  3. Embed the Chart into Default.aspx page and set the DataUri to Data.aspx.

 

Pulling the Data From SQL Server DataBase

Just to keep it simple, am going to pull the Data in an aspx page (Data.aspx.cs), build XML out of it and return.

Open Data.aspx file and remove all the html code except for Page directive. So the page should have only one line of code.

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Data.aspx.cs" Inherits="Data" %>

Now open Data.aspx.cs file and add the following code to setup a SQL Server DataBase connection inside the Page_Load event handler as shown below.

// Set the NORTHWND.MDF file path
String path = Server.MapPath("App_Data/NORTHWND.MDF");

// Set the connection string
String connectionString = "Data Source=.\\SQLEXPRESS;AttachDbFilename=" + path + ";Integrated Security=True;User Instance=True";

// Query DataBase
String query = "SELECT CategoryName, SUM(ProductSales) AS CategorySales" 
               + " FROM [Product Sales for 1997] " 
               + "GROUP BY CategoryName";

// Initialize the Sql connection
SqlConnection con = new SqlConnection(connectionString);

// Open connection
con.Open();

// Initialize DataTable class
DataTable dt = new DataTable();

// Initialize SqlDataAdapter class
SqlDataAdapter da = new SqlDataAdapter();

// Set the Sql command
da.SelectCommand = new SqlCommand(query, con);

// Fill DataSet with rows
da.Fill(dt);

// Close connection
con.Close();
 

Creating the XML Data

Now am going to build the Data XML that needs to be passed over to Visifire Chart control. Sample XML Data Looks like below.

<vc:Chart xmlns:vc="clr-namespace:Visifire.Charts;assembly=SLVisifire.Charts" Width="500" Height="300" Theme="Theme1" >

    <vc:Chart.AxesY>        
        <vc:Axis Prefix="$"></vc:Axis>
    </vc:Chart.AxesY>
    <vc:Chart.Titles>
        <vc:Title Text="Category wise Sales for the year 1997" FontSize="14"/>
    </vc:Chart.Titles>

    <vc:Chart.Series>
        <vc:DataSeries RenderAs="Column">
            <vc:DataSeries.DataPoints>
                <vc:DataPoint AxisXLabel="Beverages" YValue="102074.3100"/>
                <vc:DataPoint AxisXLabel="Condiments" YValue="55277.6000"/> 
                <vc:DataPoint AxisXLabel="Confections" YValue="80894.1400"/> 
                <vc:DataPoint AxisXLabel="Dairy Products" YValue="114749.7800"/>
                <vc:DataPoint AxisXLabel="Grains/Cereals" YValue="55948.8200"/>
                <vc:DataPoint AxisXLabel="Meat/Poultry" YValue="81338.0600"/> 
                <vc:DataPoint AxisXLabel="Produce" YValue="53019.9800"/>   
                <vc:DataPoint AxisXLabel="Seafood" YValue="65544.1800"/> 
            </vc:DataSeries.DataPoints> 
        </vc:DataSeries> 
    </vc:Chart.Series>

</vc:Chart>

You can play around with the Chart Designer to get a better picture of Visifire’s basic features.

Below is the code which generates the required XML.

// Initialize StringBuilder class
StringBuilder chartXml = new StringBuilder();

// Append chart XML data
chartXml.Append("<vc:Chart xmlns:vc=\"clr-namespace:Visifire.Charts;assembly=SLVisifire.Charts\" Width=\"500\" Height=\"300\" Theme=\"Theme1\" >");

chartXml.Append("<vc:Chart.AxesY>");
chartXml.Append("<vc:Axis Prefix=\"$\"></vc:Axis>");
chartXml.Append("</vc:Chart.AxesY>");

chartXml.Append("<vc:Chart.Titles>");
chartXml.Append("<vc:Title Text=\"Category wise Sales for the year 1997\" FontSize=\"14\"/>");
chartXml.Append("</vc:Chart.Titles>");

chartXml.Append("<vc:Chart.Series>");
chartXml.Append("<vc:DataSeries RenderAs=\"Column\" >");
chartXml.Append("<vc:DataSeries.DataPoints>");

foreach (DataRow dataRow in dt.Rows)
    chartXml.Append("<vc:DataPoint AxisXLabel=\"" + dataRow["CategoryName"].ToString() + "\" YValue=\"" + dataRow["CategorySales"].ToString() + "\"/>");

chartXml.Append("</vc:DataSeries.DataPoints>");
chartXml.Append("</vc:DataSeries>");
chartXml.Append("</vc:Chart.Series>");
chartXml.Append("</vc:Chart>");

// Write object to an HTTP response stream
Response.Write(chartXml);

 

Create Chart

Now open Default.aspx page and add the following code. First we need to add a reference to Visifire2.js file inside the Head section of Default.aspx page.

<head runat="server">
    <script type="text/javascript" src="./Visifire/Visifire2.js"></script>
</head>

Then inside the body, create a div element and add the JavaScript code which renders the Chart.

<div id="VisifireChart0">

    <script type="text/javascript">

        // Create Visifire object
        var vChart = new Visifire2('Visifire/SL.Visifire.Charts.xap', "MyChart", 500, 300);

        // Set Chart Data xml source
        vChart.setDataUri("Data.aspx?reqtime=" + (new Date()).getTime());

        // Render the chart
        vChart.render("VisifireChart0");

    </script>

</div>

 

Make sure that the path for Visifire2.js and SL.Visifire.Charts.xap files are correct. Set Default.aspx as Start Page and run the application.

Below is a snapshot of the chart.

blogimage

 

You can download the complete solution here.


DateTime Axis with Visifire

Chirag

Current release includes a major feature – DateTime Axis. If the XValue of the DataPoints are of type DateTime, Visifire automatically switches XAxis to Date Axis. For more precision on the visualization following properties can be used.

Two properties have been introduced:

  1. XValueType in DataSeries, and
  2. IntervalType in AxisX.

XValueType can have any of these following values

  • Auto (Default)
  • Numeric
  • Date
  • DateTime, or
  • Time

IntervalType property can have any of these following values

  • (Default) Auto
  • Number
  • Years
  • Months
  • Weeks
  • Days
  • Hours
  • Minutes
  • Seconds, or
  • Milliseconds

By default the XValueType is set to Date, if XValue is of type DateTime. To consider both date & time in the axis, XValueType should be set to DateTime. If you want to consider only the Time part of DateTime, it can be done so by setting XValueType to Time.

IntervalType will be set to the most relevant one internally, according to XValues. However, it can be set manually according to the requirement.

Below are some samples for DateTime Axis.

DateTime Axis Example:

<vc:Chart Name="MyChart" Theme="Theme1" xmlns:vc="clr-namespace:Visifire.Charts;assembly=SLVisifire.Charts"
          Width="500" Height="300" ScrollingEnabled="False">

    <vc:Chart.Titles>
        <vc:Title Text="DateTime Axis"/>
    </vc:Chart.Titles>

    <vc:Chart.AxesX>
        <vc:Axis IntervalType="Days">
        </vc:Axis>
    </vc:Chart.AxesX>

    <vc:Chart.Series>
        <vc:DataSeries RenderAs="Column" XValueType="DateTime">
            <vc:DataSeries.DataPoints>
                <vc:DataPoint XValue="1/30/2000 12:00:12" YValue="20"/>
                <vc:DataPoint XValue="2/15/2000 10:12:4" YValue="10"/>
                <vc:DataPoint XValue="3/02/2000 23:00:6" YValue="30"/>
                <vc:DataPoint XValue="2/03/2000 18:45:10" YValue="40"/>
                <vc:DataPoint XValue="2/02/2000 12:00:00" YValue="15"/>
                <vc:DataPoint XValue="2/28/2000 12:22:00" YValue="28"/>
            </vc:DataSeries.DataPoints>
        </vc:DataSeries>
    </vc:Chart.Series>
</vc:Chart>

Click to see DateTimeAxis in action

Date Axis Example:

<vc:Chart Name="MyChart" Theme="Theme1" xmlns:vc="clr-namespace:Visifire.Charts;assembly=SLVisifire.Charts" Width="500" Height="300" ScrollingEnabled="False">

    <vc:Chart.Titles>
        <vc:Title Text="Date Axis"/>
    </vc:Chart.Titles>

    <vc:Chart.AxesX>
        <vc:Axis IntervalType="Months" Interval="1">
        </vc:Axis>
    </vc:Chart.AxesX>

    <vc:Chart.Series>
        <vc:DataSeries RenderAs="Column" XValueType="Date">
            <vc:DataSeries.DataPoints>
                <vc:DataPoint XValue="1/5/2000 12:00:12" YValue="20"/>
                <vc:DataPoint XValue="2/8/2000 10:12:4" YValue="10"/>
                <vc:DataPoint XValue="3/2/2000 23:00:6" YValue="30"/>
                <vc:DataPoint XValue="2/3/2000 18:45:10" YValue="40"/>
                <vc:DataPoint XValue="4/2/2000 12:00:00" YValue="15"/>
                <vc:DataPoint XValue="5/6/2000 12:22:00" YValue="28"/>
            </vc:DataSeries.DataPoints>
        </vc:DataSeries>
    </vc:Chart.Series>
</vc:Chart>

Click to see DateAxis in action

Time Axis Example:

<vc:Chart Name="MyChart" Theme="Theme1" xmlns:vc="clr-namespace:Visifire.Charts;assembly=SLVisifire.Charts" Width="500" Height="300" ScrollingEnabled="False">

     <vc:Chart.Titles>
         <vc:Title Text="Time Axis"/>
     </vc:Chart.Titles>

     <vc:Chart.AxesX>
         <vc:Axis IntervalType="Seconds">
         </vc:Axis>
     </vc:Chart.AxesX>

     <vc:Chart.Series>
         <vc:DataSeries RenderAs="Column" XValueType="Time">
             <vc:DataSeries.DataPoints>
                 <vc:DataPoint XValue="1/30/2000 1:00:12" YValue="20"/>
                 <vc:DataPoint XValue="2/15/2000 2:2:4" YValue="10"/>
                 <vc:DataPoint XValue="3/02/2000 2:12:6" YValue="30"/>
                 <vc:DataPoint XValue="2/03/2000 2:28:10" YValue="40"/>
                 <vc:DataPoint XValue="8/02/2000 3:12:6" YValue="30"/>
                 <vc:DataPoint XValue="2/04/2000 8:12:10" YValue="40"/>
             </vc:DataSeries.DataPoints>
         </vc:DataSeries>
     </vc:Chart.Series>
 </vc:Chart>

Click to see TimeAxis in action

Cheers,

Team Visfire


Drilldown Silverlight Charts using Visifire

Chirag

Creating Drilldown chart is a common requirement in any RIA dashboard. Drilldown charts give rich user experience. In this blog let’s see how we can create drilldown charts using Visifire.

In this sample application, chart can be drilled down till 2 levels. The default chart would show yearly sales of a fictitious company for the period 2006-2008. On click of column representing the sales for an year, monthly sales for that year is shown up. Further it can be drilled down to find product wise sales for the selected month.

This sample uses Javascript API to generate charts. The complete application can be downloaded from here. The code is completely commented & explained wherever necessary. Refer the rest of the blog if you need more help.

Click to see the sample in action

Data can be pulled in from any data source. To keep the example simple let’s store the sales data in an array.

var sales;
// Create array for the Sales data
sales = [{year: 2006, month: "Jan", ProductX: 20000, ProductY: 25000, ProductZ: 15000},
         {year: 2006, month: "Feb", ProductX: 10000, ProductY: 23000, ProductZ: 25000},
         {year: 2006, month: "Mar", ProductX: 22000, ProductY: 38000, ProductZ: 83000},
         {year: 2006, month: "Apr", ProductX: 23456, ProductY: 32435, ProductZ: 24223},
         {year: 2006, month: "May", ProductX: 25142, ProductY: 32415, ProductZ: 10923},
         {year: 2006, month: "Jun", ProductX: 18254, ProductY: 15342, ProductZ: 10934},
         {year: 2006, month: "Jul", ProductX: 18562, ProductY: 19832, ProductZ: 10293},
         {year: 2006, month: "Aug", ProductX: 28376, ProductY: ..............

Construct the XML string from the data stored in the array.

function getYearlySales()
{
    isChart1Added = true;
    var myXAML;
    // Constructing Data XAML
    myXAML = '<vc:Chart Theme="Theme2" Width="650" Height="450" ColorSet="Visifire1" Background="Black" xmlns:vc="clr-namespace:Visifire.Charts;assembly=SLVisifire.Charts" >' + "\n" + "\n";
    myXAML = myXAML + '<vc:Chart.Titles>' + "\n";
    myXAML = myXAML + '<vc:Title Text= "Yearly Sales" />' + "\n";
    myXAML = myXAML + '</vc:Chart.Titles>' + "\n";
    myXAML = myXAML + '<vc:Chart.PlotArea>' + "\n";
    myXAML = myXAML + '<vc:PlotArea Background= "#0A0A0A" />' + "\n";
    myXAML = myXAML + '</vc:Chart.PlotArea>' + "\n";
    myXAML = myXAML + '<vc:Chart.AxesX>' + "\n";
    myXAML = myXAML + '<vc:Axis Title="Year" />' + "\n";
    myXAML = myXAML + '</vc:Chart.AxesX>' + "\n";
    myXAML = myXAML + '<vc:Chart.AxesY>' + "\n";
    myXAML = myXAML + '<vc:Axis Title="Amount" Prefix="$" />' + "\n" + "\n";
    myXAML = myXAML + '</vc:Chart.AxesY>' + "\n";
    myXAML = myXAML + '<vc:Chart.Series>' + "\n";
    myXAML = myXAML + '<vc:DataSeries RenderAs="Column">' + "\n";
    myXAML = myXAML + '<vc:DataSeries.DataPoints>' + "\n";
    sales.sort(sortByYear);
    var totalSales = 0;
    currYear = sales[0].year;
    for (var arrayIndex = 0; arrayIndex < sales.length; arrayIndex++)
    {
        if(sales[arrayIndex].year == currYear)
        {
            currYear = sales[arrayIndex].year;
            totalSales += sales[arrayIndex].ProductX + sales[arrayIndex].ProductY + sales[arrayIndex].ProductZ;
        }
        else
        {
            myXAML = myXAML + '<vc:DataPoint AxisXLabel="' + currYear + '" YValue="' + totalSales + '"/>' + "\n";
            totalSales = 0;
            currYear++;
        }
    }
    myXAML = myXAML + '<vc:DataPoint AxisXLabel="' + currYear + '" YValue="' + totalSales + '"/>' + "\n";
    myXAML = myXAML + '</vc:DataSeries.DataPoints>' + "\n";
    myXAML = myXAML + "\n" + '</vc:DataSeries>' + "\n";
    myXAML = myXAML + '</vc:Chart.Series>' + "\n";
    myXAML = myXAML + '</vc:Chart>';
    return myXAML;
}

First, create the chart for yearly sales. Next, attach an event handler for “MouseLeftButtonUp” event to the DataSeries. On fire of this event, this chart is replaced with a chart with monthly sales for the year represented by the selected DataPoint in that DataSeries. Event handler can be attached as shown in the code snippet below.

// Attaching event handler for MouseLeftButtonUp event
vChart1.preLoad = function(args) {
    chart1 = args[0];
    chart1.Series[0].MouseLeftButtonUp = function(e) {
        onMouseUpMonthlySales(e.AxisXLabel); //Calling the function to replace the chart
    };
};

Use the same logic to replace this chart with a chart with product wise sales for the selected month. The crux of a drilldown chart is to attach an event handler to update the chart on fire of some event. I think we have accomplished the same swiftly in this sample. A link/button to return back to the previous state of the chart would give a holistic user experience.

You can see the sample in action here. The complete solution can be downloaded from here.

Cheers,

Team Visifire.


Visifire v1.5.8 released

Chirag

Hi,

As promised we are supporting both Visifire 1.x & Visifire 2.x in parallel. In this release of Visifire 1.x series, we have added Date support for AxisX. One of our premium customer got this feature developed. Now, we are releasing it to public. We have introduced new property – XValueType in AxisX, it can be either Numeric or DateTime. Interval Type for the AxisX is Day. Date can be set to property – XValue of DataPoint. Date can be formatted using property – ValueFormatString of AxisX.

Visifire Chart with Date Axis

Visifire Chart with Date Axis

Below is the Managed Code Snippet using Date support for AxisX.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Visifire.Charts;
using Visifire.Commons;

namespace ChartApp
{
    public partial class Page : UserControl
    {
        public Page()
        {
            InitializeComponent();
            CreateChart();
        }
        private void CreateChart()
        {
            Chart chart = new Chart();
            chart.Height = 300;
            chart.Width = 500;

            // Creating AxisX
            AxisX axisX = new AxisX();
            axisX.XValueType = XValueTypes.DateTime;

            // Date time standard format
            axisX.ValueFormatString = "d/M/yyyy";

            // To avoid auto skip
            axisX.Interval = 1;
            chart.Children.Add(axisX);

            //Creating DataSeries
            DataSeries dataSeries = new DataSeries();
            dataSeries.RenderAs = "Column";

            // Adding 1st DataPoint
            DataPoint dp = new DataPoint();
            dp.XValue = new DateTime(2008,2,1);
            dp.YValue = 345;
            dataSeries.Children.Add(dp);

            // Adding 2nd DataPoint
            dp = new DataPoint();
            dp.XValue = new DateTime(2008, 2, 4);
            dp.YValue = 222;
            dataSeries.Children.Add(dp);

            // Adding 3rd DataPoint
            dp = new DataPoint();
            dp.XValue = new DateTime(2008, 2, 20);
            dp.YValue = 533;
            dataSeries.Children.Add(dp);

            // Adding DataSeries to Chart
            chart.Children.Add(dataSeries);
            this.LayoutRoot.Children.Add(chart);
        }
    }
}

Below is the XML Snippet using Date support for AxisX.
<vc:Chart xmlns:vc=”clr-namespace:Visifire.Charts;assembly=Visifire.Charts” Theme=”Theme1″>
<vc:Title Text=”Date Axis”/>
<vc:AxisX XValueType=”DateTime” ValueFormatString=”d/M/yyyy” Interval=”1″/>
<vc:DataSeries RenderAs=”Column”>
<vc:DataPoint XValue=”2/1/2008″ YValue=”345″/>
<vc:DataPoint XValue=”2/4/2008″ YValue=”222″/>
<vc:DataPoint XValue=”2/20/2008″ YValue=”533″/>
</vc:DataSeries>
</vc:Chart>

Download Visifire v1.5.8 here.

Cheers,
Team Visifire


New font properties in Visifire v1.0.13

vivek

With this new release we have introduced few new features.

  • Embedding fonts in Visifire - With this new feature you can embed fonts which can be applied to the FontFamily of any Text element. Let’s take a look at the example below

<vc:Title Text="Visifire Charts" FontFamily="Mtcorsva.ttf#Monotype Corsiva" />

Here FontFamily is set in the Title element, the font file that I have used is "Mtcorsva.ttf". This file is located  in ClientBin folder. It can be present anywhere in the same application domain. The font file can be a " *.ttf " or " *.zip " file.

The format followed to specify the font has two parts : font file name followed by a hash (#) and the comma separated list of fonts.

FontFamily="<font_file> # <font_name_1>,< font_name_2>"

Until the font file gets downloaded default font will be applied. You can also put an archived font file with the same syntax:

<vc:Title Text="Visifire Charts" FontFamily="Mtcorsva.zip#Monotype Corsiva" />

This format is applicable where ever FontFamily is used. Have a look at the Documentation for more details.

The following is the screenshot of "Embedded Font" example.

EmbeddedFontImage 

 

  • Multi-Line Text - This feature will help you to display text in multiple lines. All you need to do is just put "\n" in the text property of any Text attribute of an element as shown below:

<vc:Title Text="Athens 2004 \n Olympics"/>

Multi-Line text is applicable to all text content in Visifire. Have a look at the Documentation for more details.

The following is the screenshot of "Multi-Line Text" example.

MultiLineImage


Sparkline Charts using Visifire

karthik

In this blog I’ll show how to create Sparkline Charts using Line charts from Visifire.

Let me start by showing a sample of the sparkline chart: image

The following XML is a bare bone XML required to create sparkline charts:

<vc:Chart xmlns:vc="clr-namespace:Visifire.Charts;assembly=Visifire.Charts"
AnimationEnabled="False" Padding="1" BorderThickness="0" Watermark="False"> 

  <vc:AxisX Enabled="False"/>
  <vc:AxisY Enabled="False" StartFromZero="False"/> 

  <vc:DataSeries RenderAs="Line" LabelEnabled="False" MarkerEnabled="False" >
    .
    .
    .
  </vc:DataSeries> 

</vc:Chart>

Highlighting of the various points has to be done by selecting the color for the marker.

To highlight any point you have to enable the marker for the point and set the color. If color is not selected then default color will be applied. Also set the marker size as per requirement. Have a look at the example below, it shows how to highlight the start and end points.

<vc:Chart xmlns:vc="clr-namespace:Visifire.Charts;assembly=Visifire.Charts" Theme="Theme1"
          AnimationEnabled="False" Padding="1" BorderThickness="0" Watermark="False"> 

  <vc:AxisX Enabled="False"/>
  <vc:AxisY Enabled="False" StartFromZero="False"/> 

  <vc:DataSeries RenderAs="Line" LabelEnabled="False" MarkerEnabled="False"
                 MarkerSize="5" LineThickness="0.5" Color="Black">
    <vc:DataPoint YValue="44.01" MarkerEnabled="True" Color="Blue" />
    .
    .
    .
    <vc:DataPoint YValue="44.5" MarkerEnabled="True" Color="Blue" />
  </vc:DataSeries> 

</vc:Chart>

Any point can be highlighted to show its importance

The screen shot below shows a HTML table containing Visifire sparkline charts, click on the image below to see silverlight example:

 image

The code for this example can be downloaded from the here.

Visifire sparkline charts support all events that are supported by line charts and hence can be easily used for creating drill down charts.


Real-time Charts using Visifire

karthik

With the latest version of Visifire you can re-render the charts from JavaScript. I’ll show how to use this feature to create a real time chart.

To create real-time charts from JavaScript follow these steps:

  1. Create a chart.
  2. Call a function to get updated XML.
  3. Call render function to display the chart.
  4. Repeat from step 2.

It’s that simple, see the JavaScript code below:

<div id="Div1">
    <script type="text/javascript">  

        //Create new chart
        var vChart1 = new Visifire('ClientBin/Visifire.xap',500,300); 

        //An array to store data
        var data = new Array(50); 

        //Initialize array with default values
        data = initializeData(data); 

        function update()
        {
            //Update array with latest data
            data = updateData(data); 

            //Generate chart XML using latest data
            var chartXML = updateChartXML(data); 

            //Set the XML for the chart
            vChart1.setDataXml(chartXML); 

            //Call render to display the chart
            vChart1.render("Div1"); 

            //Repeat after every second
            setTimeout(update,1000);
        } 

        //update the chart
        update(); 

    </script>
</div>

The following image is the screen shot of real-time chart example. Click on the image see it in action:

image

You can download the source for this example here.

The re-rendering process can also be used if the updated XML is stored in files, by using the chart.setDataUri function.


Next Page »