Sue Hernandez's SharePoint Blog

SharePoint and Related Stuff

Silverlight Gantt Part 6

At long last I’m getting back to my posts with the Silverlight Gantt Chart.  I had a request to post the source code, and if I can clean it properly, I will do so – probably in my next (final) post.

Getting the X Axis to have a dynamic interval such that it only shows about 6 -7 points at a time

By default, it shows so many points on the X axis that your points either run into each other or get put on 2 lines.  So this is a way to control how many points get shown.

This one’s easy – you just need to calculate a numerical value and set the interval in code.  I’m sure my math isn’t perfect, but this was my quick n dirty way to calculate and then set the interval .

// Set the Interval so we don’t get 2 rows of labels, which 
// seems to be the default
int maxNumOfLabelValues = 4;
int interval = 1;

if(max > 10000)
{
     interval = Convert.ToInt32((Math.Round((max / 10000)) * 10000) / maxNumOfLabelValues);
}
elseif(max > 1000)
{
     interval = Convert.ToInt32((Math.Round((max / 1000)) * 1000) / maxNumOfLabelValues);
}
elseif(max > 100)
{
     interval = Convert.ToInt32((Math.Round((max / 100)) * 100) / maxNumOfLabelValues);
}
elseif(max > 10)
{
     interval = Convert.ToInt32((Math.Round((max / 10)) * 10) / maxNumOfLabelValues);
}

// Set the axis data
((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;

 Getting the X Axis to Rotate

I wanted to show the X Axis point labels in such a way that they didn’t overlap on top of one another.  So we apply a transform to the XAML to rotate the labels by a negative 60 degrees.

<!– X Axis –>
<Style x:Key=”HorizontalAxisStyle” TargetType=”chartingToolkit:AxisLabel”>
     <Setter Property=”Margin” Value=”0,5,0,0″/>
     <Setter Property=”Template”>
          <Setter.Value>
               <ControlTemplate TargetType=”chartingToolkit:AxisLabel”>
                    <layout:LayoutTransformer>
                         <layout:LayoutTransformer.LayoutTransform>
                              <RotateTransform Angle=”-60″ />
                         </layout:LayoutTransformer.LayoutTransform>
                         <TextBlock Padding=”0″ DataContext=”{Binding}”
                              Text
=”{Binding Converter={StaticResource AxisDateFormatConverter}, ConverterParameter={StaticResource axisMinDate}}” />
                    </layout:LayoutTransformer>
               </ControlTemplate>
          </Setter.Value>
     </Setter>
</Style>

 Getting “Extra Stuff” inside the Y Axis Label area

I wanted to put some “extra” items inside the Y axis label – not just the label of the data point, but also some extra information about that data point.  So for example I wanted to put a glassy ball-dot kind of thing, representing the “health” of the project, as well as putting the project name, as well as putting some blurb about the status of the project.

The first thing I had to do was to create a Data Item Object (did I show you this object in an earlier post?) and then a custom class for the Gantt Y Axis object.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

namespace SilverlightGantt
{
     public class DataItem
        {
          public string Key { get; set; }
          public DateTime MinDate { get; set; }
          public double StartDate { get; set; }
          publicd ouble EndDate { get; set; }
          public string TextLabelMargin { get; set; }
          public string Foreground { get; set; }
          
public string DotBackground { get; set; }
          public string LabelText { get; set; }
          public string ExtraStuffVisibility { get; set}

          public DateTime StartDateDate { get; set; }
          public DateTime EndDateDate { get; set; }

          public string FormattedValue
          {
               get
                         {
                                   return string.Format(“{0:MM/dd/yyyy}”, EndDateDate);
              
}
                }

               public void SetDateDoubles()
         
{
                        if (MinDate != DateTime.MinValue)
              
{
                                 StartDate = (StartDateDate.Subtract(MinDate)).Days;
                                 EndDate = (EndDateDate.Subtract(MinDate)).Days;
                        }
               }

        public DataItem(string _key, DateTime _start, DateTime _end, string _margin, string _foreground)
        
{
                      Key = _key;
                      StartDateDate = _start;
                      EndDateDate = _end;
                      Foreground = _foreground;
             }

        public DataItem()
       
{
             }
       }
}

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

namespace SilverlightGantt
{
     [StyleTypedProperty(Property = “AxisLabelStyle”, StyleTargetType = typeof(AxisLabel))]

     public class GanttYAxisCategoryAxis
        {
          public GanttYAxis()
                {
                }

          protected
overridevoid PrepareAxisLabel(Control label, object dataContext)
                {
               object newCTX = null;

               object ctx = this.DataContext;
               DataItem[] allItems = ctx as DataItem[];
               if (allItems != null)

                        {
                   foreach (DataItem item in allItems)

                               {
                                       if(dataContext.ToString() == item.Key)
                                       {
                                                 newCTX = item;
                             break;
                                      }
                              }
                      }

             base.PrepareAxisLabel(label, newCTX);
               }
       }
}

So the next thing I had to do was to put everything in the Control Template for the Y Axis that I wanted to see, and then add binding to be able to fill in that information.

<!– Y Axis –>
<Style x:Key=”VerticalAxisStyle” TargetType=”chartingToolkit:AxisLabel”>
     <Setter Property=”Margin” Value=”0,0,5,0″/>
     <Setter Property=”HorizontalAlignment” Value=”Left” />
     <Setter Property=”Template”>
          <Setter.Value>
               <ControlTemplate TargetType=”chartingToolkit:AxisLabel”>
                    <StackPanel x:Name=”xAxisStackPanel” MinHeight=”37″ Orientation=”Horizontal” HorizontalAlignment=”Left” Margin=”0,0,5,0″>
                         <!– Project Name : Key –>
                         <TextBlock Visibility=”{Binding ExtraStuffVisibility}” Text=”{Binding Key}” TextWrapping=”Wrap” Width=”75″ 
                              HorizontalAlignment
=”Left” VerticalAlignment=”Center” />
                         <!– Glassy Dot : DotBackground –>
                         <Grid Margin=”5,0,0,0″ Visibility=”{Binding ExtraStuffVisibility}”>
                              <Ellipse Fill=”{Binding DotBackground}” HorizontalAlignment=”Left” Stroke=”Black” Width=”25″ Height=”25″/>
                              <Ellipse HorizontalAlignment=”Left” StrokeThickness=”1″ Stroke=”{Binding DotBackground}” Width=”25″ Height=”25″ Opacity=”0.5″>
                                   <Ellipse.Fill>
                                        <LinearGradientBrush EndPoint=”0.5,1″ StartPoint=”0.5,0″>
                                             <GradientStop Color=”#3FFFFFFF”/>
                                             <GradientStop Color=”#00787878″ Offset=”0.5″/>
                                             <GradientStop Color=”#99000000″ Offset=”1″/>
                                        </LinearGradientBrush>
                                   </Ellipse.Fill>
                              </Ellipse>
                              <Ellipse HorizontalAlignment=”Left” StrokeThickness=”0″ Stroke=”{Binding DotBackground}” Width=”25″ Height=”25″>
                                   <Ellipse.Fill>
                                        <RadialGradientBrush>
                                             <GradientStop Color=”#99000000″ Offset=”1″/>
                                             <GradientStop Color=”#66FFFFFF”/>
                                        </RadialGradientBrush>
                                   </Ellipse.Fill>
                              </Ellipse>
                              <Ellipse HorizontalAlignment=”Left” Margin=”5,2,0,0″ VerticalAlignment=”Top” Width=”15″ Height=”15″>
                                   <Ellipse.Fill>
                                        <LinearGradientBrush EndPoint=”0.5,1″ StartPoint=”0.5,0″>
                                             <GradientStop Color=”Transparent” Offset=”1″/>
                                             <GradientStop Color=”#BAFFFFFF”/>
                                        </LinearGradientBrush>
                                   </Ellipse.Fill>
                              </Ellipse>
                         </Grid>
                         <!– Status Message : LabelText –>
                         <TextBlock Margin=”5,0,0,0″ Visibility=”{Binding ExtraStuffVisibility}” TextWrapping=”Wrap” Text=”{Binding LabelText}”
                              Width
=”100″ Height=”Auto”HorizontalAlignment=”Left” VerticalAlignment=”Center” />
                    </StackPanel>
               </ControlTemplate>
          </Setter.Value>
     </Setter>
</Style>

Then I needed to update my Grid XAML to reference the custom Gantt Y Axis object:

<Grid x:Name=”LayoutRoot” Background=”White”>
     <me:GanttChart x:Name=”mcChart” Margin=”0″ BorderBrush=”Transparent” Height=”400″ Width=”500″
          Style=”{StaticResource ChartStyle1}”>
          <chartingToolkit:Chart.Series>
               <me:GanttBarSeries x:Name=”BarSeries1″ DataPointStyle=”{StaticResource BarTemplateStyle1}”>
                    <chartingToolkit:BarSeries.DependentRangeAxis>
                         <chartingToolkit:LinearAxis Orientation=”X” AxisLabelStyle=”{StaticResource HorizontalAxisStyle}” />
                    </chartingToolkit:BarSeries.DependentRangeAxis>
                    <chartingToolkit:BarSeries.IndependentAxis>
                         <me:GanttYAxis x:Name=”customYAxis” Orientation=”Y” AxisLabelStyle=”{StaticResource VerticalAxisStyle}” />
                    </chartingToolkit:BarSeries.IndependentAxis>
               </me:GanttBarSeries>
          </chartingToolkit:Chart.Series>
     </me:GanttChart>
</Grid>

And finally I needed to set the Data Context for the GanttYAxis to the data points in the MainPage.xaml.cs codebehind where I’m setting everything up.

// Points show from bottom to top, so reverse it to show “1” at the top
dataPoints.Reverse();
((BarSeries)(mcChart.Series[0])).ItemsSource = dataPoints.ToArray();
((GanttYAxis)(((BarSeries)(mcChart.Series[0])).IndependentAxis)).DataContext = dataPoints.ToArray();

~Sue

Advertisements

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: