tags:

views:

41

answers:

1

I am looking to create a task profiler in WPF with an UI similar to the one of incredibuild.

Eg, timed tasks appear as strips on their respective line. Have a look at:

http://baoz.net/wp-content/2009/06/ib1.png

to see what I mean. I am unsure what the best way to tackle this problem is? Should I override the Panel class creating a custom layout panel for this or might there be an existing control/library out there that can fit my needs. I have so far had a look at various charting controls but am unsure of weither they can be tweaked to achieve this behaviour or not. I am really hoping for someone who has been using WPF for a while to help me narrow down my search. It is not exactly easy to know what to google for either :)

+1  A: 

In WPF this kind of chart is absolutely trivial. No special charting package is required:

In your resources, define a DataTemplate for displaying the event whose width is bound to the event length:

  <DataTemplate TargetType="{x:Type local:Event}">
    <Border Width="{Binding EventLength}">  <!-- This sets the width -->
      <Border Margin="1" Padding="1" StrokeThickness="1" Stroke="Black"
              Background="{Binding EventColor}"> <!-- Actual border -->
        <TextBlock Text="{Binding EventDescription}" />
      </Border>
    </Border>
  </DataTemplate>

Also define a horizontal items panel template:

  <ItemsPanelTemplate x:Key="HorizontalPanel"><DockPanel/></ItemsPanelTemplate>

Now your actual chart is trivial to build:

<ItemsControl ItemsSource="{Binding CPUs}">
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <DockPanel>
        <TextBlock Width="100" Text="{Binding Name}" /> <!-- CPU name -->
        <Rectangle Width="1" Fill="Black" />            <!-- Vertical divider -->
        <ItemsControl ItemsSource="{Binding Events}"    <!-- Events -->
                      ItemsPanel="{StaticResource HorizontalPanel}" />
      </DockPanel>
    </DataTemplate>
  </ItemsControl.Template>
</ItemsControl>

If you have gaps between your events, simply add a "Gap" object to your Events collection to represent them, then add a DataTemplate for gaps:

<DataTemplate TargetType="{x:Type local:Gap}">
  <UIElement Width="{Binding GapWidth}" />
</DataTemplate>
Ray Burns
Thank you for this! What I was lacking information about and was confused about was how to do the gaps but if it is as simple as you say I am more than happy. I'll try it out right away.
thehan
Everything worked out fine. I even managed to add some zoom. Thank you so much for your help!
thehan
Although for future visitors I might let you know that I had to use a data template selector to choose between the gap and the event templates.
thehan
Sorry, I mislead you. No you actually don't need a data template selector. Specifically, if you remove the `ItemTemplate="{StaticResource EventTemplate}"` from my answer it will work without a template selector. I put that in there before I wrote the note at the end about the gap, then forgot to take it out. Sorry about that. I'll update my answer to fix this.
Ray Burns
But also note that my code won't work if you put an explicit `x:Key` on your `DataTemplates`. It relies on WPF picking up the right template based on `TargetType`, which it won't do if there is an explicit `x:Key`. This is generally the best plan. If you need to override a particular DataTemplate you can do so by adding a ResourceDictionary at any level in your logical tree.
Ray Burns