Sue Hernandez's SharePoint Blog

SharePoint and Related Stuff

Silverlight Gantt Part 3

In my first post, I started with a teaser of what we’re trying to accomplish; in the last post, I show you how to remove the Legend from the chart.

PUTTING A “TODAY” LINE ON THE CHART

The way I handled this was to create a custom class which Inherits the Chart class.

We’ll implement the new “Today” line by (1) adding a custom class; (2) adding a red line (2 px wide Rectangle) to the Control Template of the (now custom) chart; (3) Data Binding the Margin on the Rectangle to put it where it belongs; (4) Data Binding the Tool Tip; and (5) adding code to our codebehind that sets that margin by binding the data to the custom chart.

1)  Add a Custom Class

In your project, add another class file and call it something like GanttChart.cs.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.DataVisualization.Charting;

namespace SilverlightGantt
{
     public class GanttChartChart
   
{
          public string TodaysDateMargin
      

                get { return (string)GetValue(TodaysDateMarginProperty); }
         
set { SetValue(TodaysDateMarginProperty, value); }
     
}

          public static readonly DependencyProperty TodaysDateMarginProperty = DependencyProperty.Register(“TodaysDateMargin”
          
typeof(string), typeof(GanttChart), null);

      public GanttChart()
     
{
          }
     }
}

(2) Add a red line  

Inside your ChartStyle1 template for the Chart (in the UserControl.Resources section), add XAML so that the ChartAreaBorder looks like this [Get the XAML from the last post and add this to it]:

<Border x:Name=”ChartAreaBorder”
     BorderBrush
=”#FF919191″
     BorderThickness
=”1″
     Canvas.ZIndex
=”10″>
    
<Grid DataContext=”{Binding}”
          Margin
=”{Binding ElementName=testChart, Path=TodaysDateMargin}”
          x
:Name=”todaysDateLine”
          HorizontalAlignment
=”Left”
          Grid.Row
=”1″>
         
<Rectangle Fill=”Red”
               Width
=”2″>
              
<ToolTipService.ToolTip>
                   
<TextBlock x:Name=”todaysDateToolTip” Loaded=”todaysDateToolTip_Loaded” />
               </ToolTipService.ToolTip>
         
</Rectangle>
    
</Grid>
</ Border>

We also have to change the  Target Type at the top of the Style and the top of the Control Template to reflect the custom chart’s new type

<Style x:Key=”ChartStyle1″ TargetType=”me:GanttChart”>
    
<Setter Property=”Template”>
         
<Setter.Value>
              
<ControlTemplate TargetType=”me:GanttChart”>

(3) Data Binding the Margin on the Rectangle

If you copied the XAML code from above, you’ve already set the binding, but let’s talk about what this is.  Notice that I have set a DataContext property as well as the Margin property.

 <Grid DataContext=”{Binding}” Margin=”{Binding ElementName=testChart, Path=TodaysDateMargin}”

 To my understanding, the DataContext gets the current context of the DataBinding that happened on the back end.  The binding in the Margin property is giving it a “Parent” data context to look at.  The ElementName is equal to the name of your Chart, and the Path is the Public Property inside that custom Chart class that is used to bind the value. 

(4) Data Binding the Tool Tip

You will notice that in the XAML I provided I have bound the Tooltip not to data, but rather by giving it an Event Handler.  There was something about the way that Tool Tips work that was not allowing me to do a direct {Binding}

<ToolTipService.ToolTip>
    
<TextBlock x:Name=”todaysDateToolTip” Loaded=”todaysDateToolTip_Loaded” />
</ToolTipService.ToolTip>

So we need to implement this method in the Code Behind for the MainPage.xaml.cs file.

private void todaysDateToolTip_Loaded(object sender, RoutedEventArgs e)
{
     TextBlock tip = sender as TextBlock;
  
if (tip != null)
  
{
           tip.Text = DateTime.Today.ToShortDateString();
   
}
}

(5) Set the margin of the rectangle

We’ll use in this code example the “minDate” variable. 

If you recall in my first post I mentioned how I didn’t necessarily like the implementation of the Linear Axis when really you should be using a Date Time Axis.  Basically what I did was I cycled through all of my data points, and I retrieved the lowest date.  I use that as data point “0”.  All of the other dates are a Days difference from that Minimum date.  For example, one year from that date would be the X axis value “365” as that’s how many days difference there are from the minimum date.

So first you get your data, then you cycle through it to find the min and max dates.  This gives you what number the X axis “Stops” at, so you can calculate your “Interval” if you don’t want to use the default one that comes with the Chart (too many that they go on 2 lines).  We’ll cover this code a little more in a later post.

((LinearAxis)(((BarSeries)(mcChart.Series[0])).DependentRangeAxis)).Minimum = 0;
((LinearAxis)(((BarSeries)(mcChart.Series[0])).DependentRangeAxis)).Maximum = max + (max * .1);
((LinearAxis)(((BarSeries)(mcChart.Series[0])).DependentRangeAxis)).Interval = interval;

// Points show from bottom to top, so reverse it to show “1” at the top –
// dataPoints is a List<> of a Custom Class that holds the data you retrieve
dataPoints.Reverse();
((BarSeries)(mcChart.Series[0])).ItemsSource = dataPoints.ToArray();

// First render the chart to get the actual pixel width
testChart.UpdateLayout();

double leftThickness = ((LinearAxis)(((BarSeries)(mcChart.Series[0])).DependentRangeAxis)).
     GetPlotAreaCoordinate((
DateTime.Today.Subtract(minDate)).Days).Value;
testChart.TodaysDateMargin = 
string.Format(“{0},0,0,0”, leftThickness);

What we did here was we used the GetPlotAreaCoordinate from the LinearAxis class, specifying that we’re using the chart’s Dependent Axis – that’s the X axis, the one on the bottom.  Notice though how we first had to call the UpdateLayout() method, as this “renders” the chart and makes it so that the GetPlotAreaCoordinate actually works and doesn’t return 0.

In our next post we will cover adding a Text Label for the end date, and having that label be either inside or outside the box depending on how big the box was.

Advertisements

One response to “Silverlight Gantt Part 3

  1. David Andrews June 4, 2015 at 7:31 am

    Hi from the Land Down Under. I was doing well until I got to changing the type to “me:GanttChart”. I set xmlns:me=”clr-namespace:SilverlightGantt”. but Silverlight doesn’t like it when I change the type.
    I am using Silverlight 5. Could you explain how you implement this. I am enjoying doing this as a learning exercise.

    Thanks,
    David

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: