Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to give Style to WPF Toolkit Chart

Tags:

wpf

wpftoolkit

enter image description here

I am using WPF Toolkit Chart with PieChart in my WPF Application.

I want to change by default white background to Transparent in PieChart Picture..

How to give Style to Achieve that

like image 226
Avinash Singh Avatar asked Mar 03 '13 09:03

Avinash Singh


2 Answers

WPF was designed to allow you to style controls through XAML; not code. Making the plot area and legend transparent in a pie chart is also possible through styling. Unfortunately, the border around the plot area cannot be controlled using a property and instead you have to modify the entire control template. In the end using styling is probably just as tedious as writing code behind that modifies the visual tree, but to me at least, it still feels like a cleaner approach.

<chartingToolkit:Chart>
  <chartingToolkit:Chart.PlotAreaStyle>
    <Style TargetType="Grid">
      <Setter Property="Background" Value="Transparent"/>
    </Style>
  </chartingToolkit:Chart.PlotAreaStyle>

  <chartingToolkit:Chart.LegendStyle>
    <Style TargetType="visualizationToolkit:Legend">
      <Setter Property="Margin" Value="15,0"/>
      <Setter Property="VerticalAlignment" Value="Center"/>
      <Setter Property="BorderBrush" Value="Transparent"/>
      <Setter Property="Background" Value="Transparent"/>
    </Style>
  </chartingToolkit:Chart.LegendStyle>

  <chartingToolkit:Chart.Style>
    <Style TargetType="chartingToolkit:Chart">
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="chartingToolkit:Chart">
            <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}">
              <Grid>
                <Grid.RowDefinitions>
                  <RowDefinition Height="Auto" />
                  <RowDefinition Height="*" />
                </Grid.RowDefinitions>

                <visualizationToolkit:Title Content="{TemplateBinding Title}" Style="{TemplateBinding TitleStyle}" />

                <!-- Use a nested Grid to avoid possible clipping behavior resulting from ColumnSpan+Width=Auto -->
                <Grid Grid.Row="1" Margin="0,15,0,15">
                  <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="Auto" />
                  </Grid.ColumnDefinitions>

                  <visualizationToolkit:Legend x:Name="Legend" Title="{TemplateBinding LegendTitle}" Style="{TemplateBinding LegendStyle}" Grid.Column="1" />
                  <chartingprimitives:EdgePanel x:Name="ChartArea" Style="{TemplateBinding ChartAreaStyle}">
                    <Grid Canvas.ZIndex="-1" Style="{TemplateBinding PlotAreaStyle}" />
                    <!--<Border Canvas.ZIndex="10" BorderBrush="#FF919191" BorderThickness="1" />-->
                  </chartingprimitives:EdgePanel>
                </Grid>
              </Grid>
            </Border>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>
  </chartingToolkit:Chart.Style>

  <chartingToolkit:PieSeries ... />
</chartingToolkit:Chart>

The PlotAreaStyle and LegendStyle are modified to make them transparent. The border around the plot area is removed by modifying the ControlTemplate of the chart and simply commenting out the offending Border element.

like image 136
Martin Liversage Avatar answered Oct 27 '22 17:10

Martin Liversage


If you looked at visual tree you find out that you must change Background property of grid and border to change background to transparent (elements highlighted in yellow in the below picture).

enter image description here

To do that you can change color in Loaded event. First you must find EdgePanel with name ChartArea and after that you must change color of grid and border. If you want to set also background of Legend to transparent you must find Legend element and set appropriate properties.

<DVC:Chart Canvas.Top="80" Canvas.Left="10" Name="mcChart" 
   Width="400" Height="250"
   Background="Orange"
   Loaded="mcChart_Loaded">            
    <DVC:Chart.Series>
        <DVC:PieSeries Title="Experience" 
            ItemsSource="{StaticResource FruitCollection}"
            IndependentValueBinding="{Binding Path=Name}"
            DependentValueBinding="{Binding Path=Share}">                
        </DVC:PieSeries>
    </DVC:Chart.Series>           
</DVC:Chart>

Code-behind:

private void mcChart_Loaded(object sender, RoutedEventArgs e)
{
    EdgePanel ep = VisualHelper.FindChild<EdgePanel>(sender as Chart, "ChartArea");
    if (ep != null)
    {
        var grid = ep.Children.OfType<Grid>().FirstOrDefault();
        if (grid != null)
        {
            grid.Background = new SolidColorBrush(Colors.Transparent);
        }

        var border = ep.Children.OfType<Border>().FirstOrDefault();
        if (border != null)
        {
            border.BorderBrush = new SolidColorBrush(Colors.Transparent);
        }
    }

    Legend legend = VisualHelper.FindChild<Legend>(sender as Chart, "Legend");
    if (legend != null)
    {
        legend.Background = new SolidColorBrush(Colors.Transparent);
        legend.BorderBrush = new SolidColorBrush(Colors.Transparent);               
    }
}

Helper class to find child element in this case EdgePanel:

class VisualHelper
{
    public static T FindChild<T>(DependencyObject parent, string childName) where T : DependencyObject
    {
        if (parent == null) return null;

        T foundChild = null;

        int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
        for (int i = 0; i < childrenCount; i++)
        {
            var child = VisualTreeHelper.GetChild(parent, i);
            T childType = child as T;
            if (childType == null)
            {
                foundChild = FindChild<T>(child, childName);
                if (foundChild != null) break;
            }
            else if (!string.IsNullOrEmpty(childName))
            {
                var frameworkElement = child as FrameworkElement;
                if (frameworkElement != null && frameworkElement.Name == childName)
                {
                    foundChild = (T)child;
                    break;
                }
            }
            else
            {
                foundChild = (T)child;
                break;
            }
        }
        return foundChild;
    }
}
like image 40
kmatyaszek Avatar answered Oct 27 '22 16:10

kmatyaszek