imran2155
imran2155

Reputation: 111

WPF LineSeries Chart - DataPoints with different styles

I am creating a WPF/C# graph (using Charting Toolkit) which show students marks. What i'm looking for is that if marks are below 50, the DataPoint should show an ellipse and for above 50 it should show a rectangle. Currently, it is showing rectangle for all values.

XAML is:

<chartingToolkit:Chart Background="{x:Null}" Name="lineChart" Title="Students Result" 
                        VerticalAlignment="Top" Height="450" Width="550">
        <chartingToolkit:LineSeries Name="StudentMarks" Title="Student Marks" Background="Transparent"
                                            DependentValuePath="Value"
                                            IndependentValuePath="Key"
                                            ItemsSource="{Binding [0]}">

            <chartingToolkit:LineSeries.DataPointStyle>
                <Style TargetType="chartingToolkit:LineDataPoint">
                    <Setter Property="Background" Value="DarkBlue"/>
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="chartingToolkit:LineDataPoint">
                                <Grid x:Name="grdDataPointRect">
                                    <Rectangle x:Name="passed" Fill="{TemplateBinding Background}" Stroke="Black"/>
                                    <Ellipse x:Name="failed" Width="5" Height="5" Stroke="Green" StrokeThickness="1"
                                     Fill="Green" Visibility="Hidden"></Ellipse>
                                </Grid>

                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>

                </Style>
            </chartingToolkit:LineSeries.DataPointStyle>
        </chartingToolkit:LineSeries>
        <chartingToolkit:Chart.Axes>

            <chartingToolkit:LinearAxis Name="xAxis" Orientation="X" ShowGridLines="True" 
                                Minimum="1" Maximum="5" Interval="1" Title="Students" />
            <chartingToolkit:LinearAxis Name="yAxis" Orientation="Y" ShowGridLines="True" 
                                Minimum="10" Maximum="100" Interval="10" Title="Marks" />
        </chartingToolkit:Chart.Axes>
    </chartingToolkit:Chart>

C# Code is:

       private void DrawGraph()
    {
        List<KeyValuePair<int, int>> Students1 = new List<KeyValuePair<int, int>>();
        List<KeyValuePair<int, int>> Students2 = new List<KeyValuePair<int, int>>();
        var dataSourceList = new List<List<KeyValuePair<int, int>>>();

        Students1.Add(new KeyValuePair<int, int>(1, 40));
        Students1.Add(new KeyValuePair<int, int>(2, 70));
        Students1.Add(new KeyValuePair<int, int>(3, 55));
        Students1.Add(new KeyValuePair<int, int>(4, 35));
        Students1.Add(new KeyValuePair<int, int>(5, 80));

        // if marks are less then 50
        // change datapointstyle to ellipse from rectangle

        dataSourceList.Add(Students1);
        lineChart.DataContext = dataSourceList;

    }

Please guide.

Upvotes: 0

Views: 2283

Answers (1)

King King
King King

Reputation: 63317

If the chart is designed correctly, the DataContext in each DataPoint should be each data item in the List<KeyValuePair<int,int>> you set for the chart. So you can use a Converter to determine if the data item has mark below 50 or not. The Converter just check the input mark and output a bool such as when it's true meaning the student passed:

public class MarkToPassedConverter : IValueConverter {
   public object Convert(object value, Type targetType, object parameter, 
                         CultureInfo culture){
       var mark = (int) value;
       return mark >= 50;
   }
   public object ConvertBack(object value, Type targetType, object parameter, 
                             CultureInfo culture){
       throw new NotImplementedException();
   }
}

Declare the Converter as some resource in the XAML, suppose its namespace is declared as local in your XAML:

<local:MarkToPassedConverter x:Key="m2p"/>

Use ControlTemplate's Trigger to toggle the Visibility of the 2 shapes indicating different statuses based on the input mark:

<ControlTemplate TargetType="chartingToolkit:LineDataPoint">
     <Grid x:Name="grdDataPointRect">
         <Rectangle x:Name="passed" Fill="{TemplateBinding Background}" Stroke="Black" Visibility="Hidden"/>
         <Ellipse x:Name="failed" Width="5" Height="5" Stroke="Green" StrokeThickness="1"
                                 Fill="Green" Visibility="Visible"></Ellipse>
     </Grid>
     <ControlTemplate.Triggers>
         <DataTrigger Binding="{Binding Value, Converter={StaticResource m2p}}" Value="True">
             <Setter TargetName="passed" Property="Visibility" Value="Visible"/>
             <Setter TargetName="failed" Property="Visibility" Value="Hidden"/>
         </DataTrigger>             
     </ControlTemplate.Triggers>
</ControlTemplate>

Note that the Visibility of passed is hidden by default.

Upvotes: 1

Related Questions