Home > Silverlight > Showing and Hiding Series in chart

Showing and Hiding Series in chart

Lets say we have a chart like this

sh_series1

it kind of looks like too many lines and user doesnt have easy way to see the different trends or easily compare the different measures user wants.

Showing and hiding a particular series will be nice addition to charts to allow the user to pick and choose what to see.   we want the user to be able to click the legenditem to toggle the display of the series.

sh_series2

sh_series3

we will start adding a style for the LegendItem, the original style looks like this

 <Style TargetType=”charting:LegendItem”>
        <Setter Property=”IsTabStop” Value=”False” />
        <Setter Property=”Template”>
            <Setter.Value>
                <ControlTemplate TargetType=”charting:LegendItem”>
                    <StackPanel Orientation=”Horizontal”>
                        <Rectangle Width=”8″ Height=”8″ Fill=”{Binding Background}”
                                   Stroke=”{Binding BorderBrush}” StrokeThickness=”1″ Margin=”0,0,3,0″ />
                        <datavis:Title Content=”{TemplateBinding Content}” />
                    </StackPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

and we specify the style on the LineSeries like this

<charting:LineSeries   LegendItemStyle=”{StaticResource LegendItemStyle}” Title=”Total Visits”
                                     IndependentValueBinding=”{Binding OrderDate}”
                                     DependentValueBinding=”{Binding Visits}” />            

As we want to provide a way for the user to toggle the visibility of the Series. we will re-style the LegendItem to use a CheckBox for this sample

 <Style x:Key=”LegendItemStyle” TargetType=”charting:LegendItem”>
            <Setter Property=”IsTabStop” Value=”False” />
            <Setter Property=”Template”>
                <Setter.Value>
                    <ControlTemplate TargetType=”charting:LegendItem”>
                        <CheckBox Click=”CheckBox_Click” Cursor=”Hand” IsChecked=”true”
                                  Content=”{TemplateBinding Content}” Tag=”{TemplateBinding Content}”>
                            <CheckBox.Template>
                                <ControlTemplate TargetType=”CheckBox”>
                                    <StackPanel Orientation=”Horizontal”>
                                        <Rectangle Width=”8″ Height=”8″ Fill=”{Binding Background}” Stroke=”{Binding BorderBrush}”
                                                   StrokeThickness=”1″ Margin=”0,0,3,0″ />
                                        <datavis:Title Content=”{TemplateBinding Content}” />
                                    </StackPanel>
                                </ControlTemplate>
                            </CheckBox.Template>
                        </CheckBox>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

(After posting I realized that instead of binding again to Tag we could base our condition on the content itself. Too lazy to change the code now)

To start with, we want all the series to be shown so we set the IsChecked property to “true”.

we added a click handler also to checkbox in which we are going to check the IsChecked property and decide if we want the series to be shown or hidden

private void CheckBox_Click(object sender, RoutedEventArgs e)
{
CheckBox chk = (sender as CheckBox);
LineSeries ls = chart1.Series.Cast
().Where(s => s.Title.ToString() == chk.Tag.ToString()).ElementAtOrDefault(0);
if (chk.IsChecked.Value)
chk.Opacity = ls.Opacity = 1;
else
{
chk.Opacity = 0.5;
ls.Opacity = 0;
}
}

you can see a demo here and download the code here

About these ads
Categories: Silverlight Tags:
  1. Mike Greenway
    August 21, 2009 at 7:00 pm | #1

    Very Nicely done.
    Thank you

  2. Takuan Daikon
    August 25, 2009 at 3:34 pm | #2

    Doesn’t seem as if there’s a convenient way to use this for the general case of having multiple charts on the same screen, or at least it’s not obvious how that would be done.

    Thanks for the jumpstart, though, it’s much appreciated.

    • lee
      August 25, 2009 at 3:36 pm | #3

      Not sure, I understand what you are trying to do

  3. Takuan Daikon
    August 25, 2009 at 4:10 pm | #4

    Well, you have a reference to the chart hard-coded into the checkbox event handler (chart1). Since my page has four charts on it, it would seem that I can’t use the LegendItemStyle as-is on each chart, and I’m too new to Silverlight to know how to accomplish this without literally copying and pasting the style for each chart :(

    • lee
      August 25, 2009 at 4:26 pm | #5

      you could modify the function for checkbox click like below, so that chart name is not hard coded and will work for multiple charts

      private void CheckBox_Click(object sender, RoutedEventArgs e)
      {
      CheckBox chk = (sender as CheckBox);
      Chart ch = GetParent(chk);
      LineSeries ls = ch.Series.Cast().Where(s => s.Title.ToString() == chk.Tag.ToString()).ElementAtOrDefault(0);
      if (chk.IsChecked.Value)
      chk.Opacity = ls.Opacity = 1;
      else
      {
      chk.Opacity = 0.5;
      ls.Opacity = 0;
      }
      }

      //Add this function in your code behind
      public T GetParent(DependencyObject obj) where T : DependencyObject
      {
      DependencyObject parent = VisualTreeHelper.GetParent(obj);
      while (parent != null)
      {

      if (parent.GetType() == typeof(T))
      break;

      else

      parent = GetParent(parent);
      }
      return parent as T;
      }

      • Takuan Daikon
        August 25, 2009 at 5:05 pm | #6

        Excellent. I had tried looking at the .Parent property (which is always null), but had not known about the VisualTreeHelper class. Thanks a bunch!

        • lee
          August 25, 2009 at 5:07 pm | #7

          you are welcome

  4. Alexandra
    November 26, 2009 at 5:53 pm | #8

    VERY HELPFUL. I needed to use legend items to remove the series from the chart and this worked BEAUTIFULLY! Thanks so much.

  5. Matt Weyland
    January 8, 2010 at 8:24 pm | #9

    Great post, helped me with a problem with syncing up lineseries colors with an external control. I was able to modify the legend style to meet my needs and merge that with your demo and it’s workign well. Thanks.

  6. Gill Goble
    March 12, 2010 at 6:54 am | #11

    Very useful post. Please would you show me how to extend your example to a chart that has a combination of line and column series. Thanks

  7. Gill Goble
    March 12, 2010 at 7:16 am | #12

    ok, I figured it out. Just had to change

    Series ls = TheChart.Series.Cast().Where(s => s.Title.ToString() == chk.Tag.ToString()).ElementAtOrDefault(0);

    to

    Series ls = TheChart.Series.Cast().Where(s => s.Title.ToString() == chk.Tag.ToString()).ElementAtOrDefault(0);

  8. Gill Goble
    April 21, 2010 at 7:33 am | #13

    I would like to extend this ‘Showing/Hiding Series’ functionality to a chart that has both the new StackedColumnSeries (Silverlight 4) and LineSeries. Any tips?

    • lee
      April 21, 2010 at 9:49 am | #14

      Hi,
      I did not play around with stacked charts, wont a similar approach work. Are the series pointing to the same data, what issues are you having

      • Gill Goble
        April 22, 2010 at 6:51 am | #15

        Originally I had 2 line and 3 column series in a single chart and the show/hide legend check boxes were working fine. Then with the new release of Silverlight 4, I changed my 3 column series to be stacked column series. Now when I click on the legend checkbox I get error :

        “Unable to cast object of type ‘System.Windows.Controls.DataVisualization.Charting.StackedColumnSeries’ to type ‘System.Windows.Controls.DataVisualization.Charting.Series’.”

        • lee
          April 22, 2010 at 9:07 am | #16

          you have to add styles for legend and legenditem. the checkbox will go in the legenditem template and codebehind will look like this

          private void CheckBox_Click(object sender, RoutedEventArgs e)
          {
          CheckBox chk = (sender as CheckBox);
          SeriesDefinition ls = chart1.Series.Cast<StackedColumnSeries>().First().SeriesDefinitions.Where(s => s.Title.ToString() == chk.Tag.ToString()).ElementAtOrDefault(0);

          if (chk.IsChecked.Value)
          chk.Opacity = ls.Opacity = 1;
          else
          {
          chk.Opacity = 0.5;
          ls.Opacity = 0;
          }
          }
          thing is Opacity is not getting reflected correctly. we should come up with something. I will update if I find a way

          • Gill Goble
            April 23, 2010 at 8:21 am | #17

            Thanks for this Lee. I have tried out your code for the StackedColumnSeries and also did not get the Opacity to work. Also tried the Visibility property but that didn’t work either.

            Also I need to extend this to cope with both line series and stacked column series in the same chart. Any advice on this would be much appreciated.

  9. lee
    April 23, 2010 at 10:31 am | #18

    Hi,
    looks like the only way it might work, is to have not show the legend for the stackedcolumnseries and base our logic on lineseries and programatically add/remove the seriesdefinitions. opacity wont work as the points are laid out on canvas, so we have to literally remove the series definition

  10. Matthias
    May 4, 2010 at 10:11 am | #19

    Hi,
    thanks for this great article. But I need your help. I have several charts on several TabItems. The Charts show the same Informations but they use different timespans. Therefor i need to synchronize the LegendItems and LineSeries. I try to access to the differen checkboxes in the charts – but it doesn’t work. Have you an idea? Thank you

    • lee
      May 4, 2010 at 2:15 pm | #20

      Hi,
      Could you send me a sample of what you are trying to do?

      • Matthias
        May 4, 2010 at 3:41 pm | #21

        Your solution is the basis and I write down just the changes:

        1. include dll and register namespace:
        xmlns:extended=”clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls”

        2.change xaml-file

        3. Append to constructor:
        (this.chart2.Series[0] as LineSeries).ItemsSource = DataItems;
        (this.chart2.Series[1] as LineSeries).ItemsSource = DataItems;
        (this.chart2.Series[2] as LineSeries).ItemsSource = DataItems;
        (this.chart2.Series[3] as LineSeries).ItemsSource = DataItems;

        after

        (this.chart1.Series[3] as LineSeries).ItemsSource = DataItems;

        When I hide Series “Total Visits” in TabItem “View 1″ it should hide also in TabItem “View 2″.

        I hope you will understand my intension:-)

        • Matthias
          May 4, 2010 at 3:43 pm | #22

          WordPress has some problems with xaml. Can you send me an email please. I will send back my project-code to your adress. Thank you

  11. Aravind
    June 28, 2010 at 10:16 am | #23

    Guys am also facing some problem with Stackedcolumn series .. can you please mail me the code

    • lee
      June 28, 2010 at 5:02 pm | #24

      Hi,
      we did not find a solution, the series items are hosted in a canvas, so we have to come up with a way to size the item to 0(when we dont want to see the series) and back to original value (when the series is visible) as opacity wont work

      • Srini
        November 16, 2010 at 4:40 pm | #25

        I’m having the same issue. If the opacity won’t work, then why is it there?

        I tried removing the series, but the series definition that is stacked on top of the removed series falls to 0 and starts from there. So that method won’t work.

        • lee
          November 16, 2010 at 4:42 pm | #26

          It wont work when the series are stacked

  12. Biana
    July 2, 2010 at 4:52 am | #27

    Thanks,That’s great. Only problem I have is the the legend series title disappeared after I apply this template. Any idea?

    • lee
      July 2, 2010 at 9:51 am | #28

      Hi,
      Do you mean LegendTitle attribute on the Chart when specified shows up on the top of the Legend?. if so I tried and seems to show up fine.

      • Biana
        July 5, 2010 at 1:40 am | #29

        No, I mean the title of each series in the legend.

        • lee
          July 5, 2010 at 2:29 am | #30

          Hi,
          Could you send me a link to the sample project. I can take a look. May be there is something I am missing in the style

  13. Abrie
    December 8, 2011 at 9:49 am | #31

    Any Solutions to the dissaperaing legend items? Please Help

  14. Abrie
    December 8, 2011 at 10:19 am | #32

    Ok proplrm solved…

    change
    chk.Opacity = ls.Opacity = 1;

    to

    chk.Opacity = 1;
    ls.Opacity = 1;

  15. Steven Sultana
    March 14, 2012 at 12:41 pm | #33

    Hi,
    Thanks for this post, I learnt a lot from the code :)
    Could you please tell me from where you found the original style of the Legend item? Because I would like to do something similar (change the style) to other controls, but I don’t know what the original looks like to begin with.
    Thanks :)

    • lee
      March 14, 2012 at 2:22 pm | #34

      you can open the project in blend and you can start looking at legendtemplate

      • Steven Sultana
        March 14, 2012 at 9:26 pm | #35

        Oh I see. I’m actually using the WPF, that’s why I’m not using Blend. I’ll see how I can acquire it (from what I understand the free version is a trial version. I’m just using it for a small project, though, so that should be find :D)

        Thanks very much for the fast reply.

  16. Louis
    May 28, 2012 at 8:47 am | #36

    Hi lee,
    Thanks for your post.
    this code work beautifully.
    let me know something, after i unckecked one of the legenditem, one line series disappeard but tooltip stil remain when mouse cousor point the old place even line hide…
    let me know how to remove the tooltip while unckeck the specific lineseries..
    thanks..

  17. hamdi
    June 8, 2012 at 2:48 pm | #37

    hi All!
    Very interesting! but can we done the same things without writnig code in code behind’fiel.
    just by binding visibility or Opacity value to the checkbok.IsChecked property in the legend template? (of corse with converter :D)
    is it possible?
    thanx all

  1. August 8, 2009 at 5:53 pm | #1

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

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: