I have a Chart control from WPF Toolkit. The data collection bound to the line series used in the chart is dynamic, i.e., new points are added to the collection when I receive data. I noticed that because of this, the memory consumption was increasing. So, I limited the number of points displayed in the line series to 20. Following is the code.
Code Behind:
public partial class MainWindow : Window
{
ObservableCollection<ChartData> lineSeries1Data;
Thread MyThread;
LineSeries lineSeries;
ChartData objChartData;
Random r = new Random();
LineSeries temp;
public MainWindow()
{
InitializeComponent();
objChartData = new ChartData();
lineSeries1Data = new ObservableCollection<ChartData>();
AddLineSeries();
InitializeDataPoints();
MyThread = new Thread(new ThreadStart(StartChartDataSimulation));
}
private void AddLineSeries()
{
lineSeries = AddLineSeries(Brushes.Tomato);
lineSeries.DependentValuePath = "Value";
lineSeries.IndependentValuePath = "Name";
lineSeries.ItemsSource = lineSeries1Data;
simChart.Series.Add(lineSeries);
}
private LineSeries AddLineSeries(Brush lineColor)
{
temp = new LineSeries()
{
PolylineStyle = this.FindResource("PolylineStyle") as Style,
DataPointStyle = this.FindResource("LineDataPointStyle") as Style,
Style = this.FindResource("CommonLineSeries") as Style,
Tag = lineColor
};
return temp;
}
private void InitializeDataPoints()
{
lineSeries1Data.Add(new ChartData() { Name = DateTime.Now, Value = 0.0 });
Thread.Sleep(1000);
for (int i = 0; i < 2; i++)
{
lineSeries1Data.Add(new ChartData() { Name = DateTime.Now, Value = new Random().NextDouble() * 10 });
Thread.Sleep(1000);
}
}
public void StartChartDataSimulation()
{
int i = 0;
while (true)
{
Dispatcher.Invoke(new Action(() =>
{
objChartData.Name = DateTime.Now;
objChartData.Value = r.NextDouble() * 50;
lineSeries1Data.Add(objChartData);
if (lineSeries1Data.Count > 20)
{
lineSeries1Data.RemoveAt(0);
}
}));
Thread.Sleep(500);
}
}
private void btnStartCharting_Click(object sender, RoutedEventArgs e)
{
if (MyThread.ThreadState != ThreadState.Running)
{
MyThread.Start();
}
}
}
public class ChartData
{
DateTime _Name;
double _Value;
public DateTime Name
{
get
{
return _Name;
}
set
{
_Name = value;
}
}
public double Value
{
get
{
return _Value;
}
set
{
_Value = value;
}
}
}
XAML:
<Window x:Class="WpfChartExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:chrt="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit"
xmlns:datavis="clr-namespace:System.Windows.Controls.DataVisualization;assembly=System.Windows.Controls.DataVisualization.Toolkit"
Title="WPF Toolkit Dynamic Line Chart Example" Height="333" Width="1000" Closing="Window_Closing">
<Window.Resources>
<Style x:Key="PolylineStyle" TargetType="Polyline">
<Setter Property="StrokeThickness" Value="5" />
</Style>
<Style x:Key="LineDataPointStyle" TargetType="chrt:LineDataPoint">
<!--<Setter Property="Background" Value="#0077CC" />-->
<Setter Property="Background" >
<Setter.Value>
<Binding Path="Tag" RelativeSource="{RelativeSource AncestorType={x:Type chrt:LineSeries}}" />
</Setter.Value>
</Setter>
<Setter Property="BorderBrush" Value="White" />
<Setter Property="BorderThickness" Value="2" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Height" Value="10" />
<Setter Property="Width" Value="10" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="chrt:LineDataPoint">
<Grid x:Name="Root" Opacity="1">
<ToolTipService.ToolTip>
<StackPanel Margin="2,2,2,2">
<ContentControl Content="{TemplateBinding IndependentValue}" ContentStringFormat="X-Value: {0:HH:mm:ss}"/>
<ContentControl Content="{TemplateBinding DependentValue}" ContentStringFormat="Y-Value: {0:###.###}"/>
</StackPanel>
</ToolTipService.ToolTip>
<Ellipse StrokeThickness="{TemplateBinding BorderThickness}" Stroke="{TemplateBinding BorderBrush}" Fill="{TemplateBinding Background}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="CommonLineSeries" TargetType="chrt:LineSeries" BasedOn="{StaticResource {x:Type chrt:LineSeries}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="chrt:LineSeries">
<Canvas x:Name="PlotArea">
<Polyline Points="{TemplateBinding Points}" Stroke="{Binding Tag, RelativeSource={RelativeSource AncestorType={x:Type chrt:LineSeries}}}" Style="{TemplateBinding PolylineStyle}"/>
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="LinearAxisStyle" TargetType="chrt:LinearAxis">
<Setter Property="GridLineStyle">
<Setter.Value>
<Style TargetType="Line">
<Setter Property="Stroke" Value="#20000000" />
</Style>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="NonLinearAxisStyle" TargetType="chrt:DateTimeAxis">
<Setter Property="GridLineStyle">
<Setter.Value>
<Style TargetType="Line">
<Setter Property="Stroke" Value="#20000000" />
</Style>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="DateTimeAxisLabelStyle" TargetType="chrt:DateTimeAxisLabel">
<Setter Property="StringFormat" Value="{}{0:mm:ss}" />
</Style>
<Style x:Key="ChartTitleStyle" TargetType="datavis:Title">
<Setter Property="Visibility" Value="Collapsed"/>
</Style>
</Window.Resources>
<Grid Name="grdMain">
<Grid.RowDefinitions>
<RowDefinition Height="6*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<chrt:Chart x:Name="simChart" TitleStyle="{StaticResource ResourceKey=ChartTitleStyle}">
<chrt:Chart.LegendStyle>
<Style TargetType="datavis:Legend">
<Setter Property="Width" Value="0" />
</Style>
</chrt:Chart.LegendStyle>
<chrt:Chart.Axes>
<chrt:DateTimeAxis Name="xAxis" ShowGridLines="True" Orientation="X" Style="{StaticResource ResourceKey=NonLinearAxisStyle}" AxisLabelStyle="{StaticResource ResourceKey=DateTimeAxisLabelStyle}" />
<chrt:LinearAxis Orientation="Y" ShowGridLines="True" Style="{StaticResource ResourceKey=LinearAxisStyle}" />
</chrt:Chart.Axes>
<!--<chrt:LineSeries IsSelectionEnabled="True" PolylineStyle="{StaticResource ResourceKey=PolylineStyle}"
DataPointStyle="{StaticResource ResourceKey=LineDataPointStyle}"
ItemsSource="{Binding}"
IndependentValueBinding="{Binding Name}"
DependentValueBinding="{Binding Value}"
Tag="Red" Style="{StaticResource CommonLineSeries}">
</chrt:LineSeries>-->
</chrt:Chart>
<Button Name="btnStartCharting"
Grid.Row="1"
Width="Auto"
HorizontalAlignment="Right"
Margin="5"
Click="btnStartCharting_Click">
Start Charting
</Button>
</Grid>
In the above code, when I remove the first point, the graph refresh is affected. The refresh become slow and sometimes it stops refreshing. The older datapoints are also visible on the graph. Can someone guide me on making dynamic charts with WPF Toolkit?