Sue Hernandez's SharePoint Blog

SharePoint and Related Stuff

Silverlight Gantt Part 5

I have been writing a series about how to create a simple Gantt chart using the latest version of the Silverlight Toolkit.  My links are in my first post, which you can get to from above.

To continue with the topics…

CHANGING THE SERIES BAR’S TOOL TIP

The only thing we really need to do is to find the following XAML:

<ToolTipService.ToolTip>
    
<ContentControl Content=”{TemplateBinding FormattedDependentValue}” />
</ToolTipService.ToolTip>

and change it to:

<ToolTipService.ToolTip>
    
<ContentControl>
         
<StackPanel Orientation=”Horizontal”>
              
<TextBlock Text=”{Binding StartDateDate, StringFormat=\{0:MM\/dd\/yyyy\}}”></TextBlock>
               
<TextBlock Text=” – “></TextBlock>
              
<TextBlock Text=”{Binding EndDateDate, StringFormat=\{0:MM\/dd\/yyyy\}}”></TextBlock>
         
</StackPanel>
    
</ContentControl>
</ToolTipService.ToolTip>

Now here, we’re using data binding from our custom class “DataItem” which I introduced in the last post.  We’re also telling it to format the resultant value in a particular manner, by using the StringFormat extension.  So as long as you’ve been following along, you should have this part completed.  Again, as I’ve said before, we’ll go over the full code for the preparation and binding in probably the last post in this series.

GETTING THE X AXIS TO DISPLAY DATES INSTEAD OF “Days from Min Date”

As I’ve said before, this implementation seems, on the surface, to be a bit messy.  What we’re doing again, is we’re saying, go get me the earliest date (let’s call it 8/1/2011 for sake of argument).  That Date now is going to be represented as the decimal “0” on the X Axis.  Whereas the date 8/25/2011 would be represented as the number “24” on the X Axis – the number of days FROM the minimum date.

Now again, this seems messy but I did try to use the DateTimeAxis object that is provided in the Toolkit.  I couldn’t get it to work using DateTimes.  I posted a forum post and was answered that only Doubles will work as the Dependent Value, not DateTimes.  So I offer that my solution while not pretty, is probably the practical way to do it.

Ok so the first thing to do is to create another Template for the X Axis.  But we also have to make sure we have an XMLNS in our Main Page:

xmlns:layout=”clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Layout.Toolkit”

So after we put the XMLNS in the  User Control, we add this new style to the UserControl.Resources section: 

<!– 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>

and of course set this new style in the chart markup

<chartingToolkit:BarSeries.DependentRangeAxis>
     <chartingToolkit:LinearAxis
          Orientation=”X”
         
AxisLabelStyle=”{StaticResource HorizontalAxisStyle}” />
    
</chartingToolkit:BarSeries.DependentRangeAxis>
<chartingToolkit:BarSeries.IndependentAxis>

The Control Template is doing 2 things here:  (1) It is rotating the labels of the X axis by a – 60 degrees; (2) it is printing the text, data bound to the X Axis Label, and using a Converter class with a Static Resource parameter.  Let’s first talk about the AxisDateFormatConverter class.

// Converter for showing the X Axis lables as DateTimes instead of doubles
// Expects the MinDate to be the smallest date of all of the data points
public class AxisDateFormatterIValueConverter
{
     public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
          if (parameter != null)
                {
               DateTime minDate = DateTime.MinValue;
               DateTime.TryParse(parameter.ToString(), out minDate); 

               if (minDate != DateTime.MinValue && minDate != DateTime.MaxValue)
                         {
                    DateTime dt = minDate.AddDays((double)value);
                    return dt.ToShortDateString();
                         }
                }
                return value;
        }

         public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    
{
                if (parameter != null)
          
{
                        DateTime minDate = DateTime.MinValue;
              
DateTime.TryParse(parameter.ToString(), out minDate);
             
DateTime endDate = DateTime.MaxValue;
             
DateTime.TryParse(value.ToString(), out endDate); 

                       if (minDate != DateTime.MinValue && endDate != DateTime.MaxValue)
             
{
                               return (endDate.Subtract(minDate)).TotalDays;
             
}
                }

                return value;
     
}
}

This class expects to receive the MinDate value, which is the Earliest StartDateDate of all of your data points.  It takes the number that was passed in, adds those in Days to the MinDate, and returns a string version of that Date.

One of the problems with this, is how to get the MinDate parameter into the function??  Well, I chose to use a Static Resource, made up of a light-weight custom class that simply holds the value for the Min Date:

// For use with a Static Resource, to pass in as a 
// parameter to the Conversion function for the
// X Axis values
public class AxisMinDate
{
        public DateTime Value { get; set; }

     public AxisMinDate()
    
{
        }

        public override string ToString()
    
{
                return Value.ToShortDateString();
    
}
}

Then in the UserControl.Resources section, I add the reference to this custom class, and add the reference to the AxisDateFormatter class as well:

<!– Axis Value Formatter –>
<me:AxisDateFormatter x:Key=”AxisDateFormatConverter” />
<me:AxisMinDate x:Key=”axisMinDate” />

In the code-behind, when setting up the min and max date, at the same time, you set it into your resource:

// Get the Min Date and Max Date for determining the intervals
DateTime maxDate = DateTime.MinValue;
DateTime minDate = DateTime.MaxValue;

foreach (DataItem p in dataPoints)
{
        if(p.EndDateDate > maxDate)
    
{
                maxDate = p.EndDateDate;
        }

        if(p.StartDateDate < minDate)
    
{
                minDate = p.StartDateDate;
        }
}

if (minDate > DateTime.Today)
{
        minDate = DateTime.Today.Subtract(newTimeSpan(10, 0, 0, 0));
}

// Set this date into a resource for use later in styling the X axis labels:
// Instead of numbers, we use dates, calculated as the MinDate plus the
// double Value of the dataPoint (in days).
((AxisMinDate)this.Resources[“axisMinDate”]).Value = minDate;

Next up:  Updating the X Axis Interval such that it only shows about 6-7 points at one time.

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: