Quantcast
Channel: Code Forward
Viewing all articles
Browse latest Browse all 13

A Timeline Visualizer in Silverlight/C#: Part 1

$
0
0
I encountered a problem while developing an application for my current client: They needed to visualize a series of events on a timeline. Like a schedule or a Gantt chart. I couldn't find a canned solution for this, so I created one in Silverlight/C#. Ideally I want to create a templated control with declarative bindings, etc., but currently I just have it in the form of usercontrol. I figured it is still useful to share it here, since others will also have data that falls into this category, and could use ideas from this.

Here is a sample of how the control can be used. There is a bunch of UI functionality like click & drag, select/unselect item, mousewheel zoom in/zoom out, doubleclick to raise 'getdetail' event, add new item, etc. For some reason, Mousewheel works only in IE and not in Firefox. It works everywhere when you run it locally. I suspect the disparity is because of some site weirdness; I am using MS's free 10G silverlight streaming space to host the app. If anybody has any ideas, please let me know.
http://silverlight.services.live.com/invoke/105917/TimeLine%20Visualizer%20Demo/iframe.html



You can get the entire solution from filefactory: http://www.filefactory.com/file/ah13e8g/n/VisualTimelineDemo_zip.
Now, for the code. We will start looking at this from the outside in.
The relevant xaml in the page looks like this:

<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Border BorderBrush="#99000000" BorderThickness="1" CornerRadius="4,4,0,0" Margin="2" Grid.Row="0">
<TextBlock TextWrapping="Wrap" Margin="4,0,2,0" Text="Click on an item to select, click again to deselect. Double-Click outside any item to deselect globally. Click and drag to move. Use Mousewheel to zoom in/out. Doubleclick to request details of selected timeline item(s)."/>
</Border>
<local:TimeLineVisualizer Name="tl" Grid.Row="1"/>
<Border BorderBrush="#99000000" BorderThickness="1" CornerRadius="0,0,4,4" Margin="2" Grid.Row="2">
<StackPanel Orientation="Horizontal" Margin="4">
<TextBlock Margin="4,0,2,0" Text="TimeLine Item Name:"/>
<TextBox Name="ItemNameTextBox" Width="100"/>
<TextBlock Margin="4,0,2,0" Text="Start:"/>
<basics:DatePicker Name="StartDatePicker"/>
<TextBlock Margin="4,0,2,0" Text="End:"/>
<basics:DatePicker Name="EndDatePicker"/>
<Button Margin="4,0,4,0" Name="Btn_InsertTimeLine" Content="Add Item to TimeLine" Click="Button_Click"/>
</StackPanel>
</Border>
</Grid>

Class Diagram for TimeLineVisualizer:
Here is the code-behind in the page that deals with TimeLineVisualizer events:

     public Home()
{
------
tl.TimeLineChanged += (s, e) => SetTimeLineItemSource();
tl.DetailRequested += new EventHandler<DetailRequestedEventArgs>(tl_DetailRequested);
}
void tl_DetailRequested(object sender, DetailRequestedEventArgs e)
{
MessageBox.Show("'DetailRequested' event raised by TimeLine");
}
void Home_Loaded(object sender, RoutedEventArgs e)
{
SetTimeLineItemSource();
}
private void SetTimeLineItemSource()
{
tl.ItemsSource = from t in DataAccess.TimeLines
where ExtensionMethods.Intersects(t.Start, t.End, tl.StartDate.Value, tl.EndDate.Value)
select t;
}
The “ExtensionMethods.Intersects” method justs tells you if 2 date ranges intersect:

     //not really an extension method
public static bool Intersects(DateTime r1Start, DateTime r1End, DateTime r2Start, DateTime r2End)
{
return (r1Start == r2Start) || (r1Start > r2Start ? r1Start <= r2End : r2Start <= r1End);
}
In the next entry, we will look at the TimeLineVisualizer usercontrol.

Viewing all articles
Browse latest Browse all 13

Trending Articles