I am trying to use the radchart to display data in a stacked bar chart. While I can get the data to display, the performance is terrible when the number of stacked bars is increased. For example, 20 bins, with 30 stacks takes almost 40 seconds to appears on the screen. The whole time the chart is being updated, the UI is locked/unresponsive. Below is the code in a sample app I constructed to demonstrate the problem. If needed, I can provide a zip of the entire sample project. Are there any tips on how to improve the charting performance given the example code below?
Regards,
Doug
Xaml code
C# Code-behind
Regards,
Doug
Xaml code
<
UserControl
x:Class
=
"RadchartSLDemo.MainPage"
xmlns:telerik
=
"http://schemas.telerik.com/2008/xaml/presentation"
mc:Ignorable
=
"d"
d:DesignHeight
=
"300"
d:DesignWidth
=
"400"
>
<
Grid
x:Name
=
"LayoutRoot"
Background
=
"White"
>
<
Grid.RowDefinitions
>
<
RowDefinition
Height
=
"Auto"
/>
<
RowDefinition
Height
=
"*"
/>
</
Grid.RowDefinitions
>
<
StackPanel
Margin
=
"10"
>
<
Button
Content
=
"(re)load Data"
Click
=
"Button_Click"
Width
=
"128"
Margin
=
"5"
Height
=
"64"
/>
<
StackPanel
Orientation
=
"Horizontal"
>
<
TextBlock
Text
=
"Num bins: "
/>
<
TextBox
x:Name
=
"Bins"
Text
=
"50"
Margin
=
"10,0,0,0"
/>
<
TextBlock
Text
=
"Num stacks: "
Margin
=
"10,0,0,0"
/>
<
TextBox
x:Name
=
"Stacks"
Text
=
"30"
Margin
=
"10,0,0,0"
/>
</
StackPanel
>
<
StackPanel
Orientation
=
"Horizontal"
>
<
TextBlock
Text
=
"Chart Rebind Time:"
/>
<
TextBlock
x:Name
=
"TimeBlock"
Text
=
"N/A"
Margin
=
"10,0,0,0"
/>
</
StackPanel
>
</
StackPanel
>
<
telerik:RadBusyIndicator
x:Name
=
"BusyIndicator"
Grid.Row
=
"1"
>
<
telerik:RadChart
x:Name
=
"radChart1"
UseDefaultLayout
=
"False"
>
<
Grid
x:Name
=
"ChartGrid"
>
<
Grid.ColumnDefinitions
>
<
ColumnDefinition
Width
=
"*"
/>
<
ColumnDefinition
Width
=
"Auto"
/>
</
Grid.ColumnDefinitions
>
<
telerik:ChartArea
x:Name
=
"DataChartArea"
LegendName
=
"DataChartLegend"
Height
=
"Auto"
Width
=
"Auto"
Grid.Column
=
"0"
>
</
telerik:ChartArea
>
<
telerik:ChartLegend
Visibility
=
"Collapsed"
x:Name
=
"DataChartLegend"
Header
=
"Legend:"
VerticalAlignment
=
"Top"
Height
=
"Auto"
Width
=
"Auto"
Grid.Column
=
"1"
>
</
telerik:ChartLegend
>
</
Grid
>
</
telerik:RadChart
>
</
telerik:RadBusyIndicator
>
</
Grid
>
</
UserControl
>
C# Code-behind
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Net;
using
System.Windows;
using
System.Windows.Controls;
using
System.Windows.Documents;
using
System.Windows.Input;
using
System.Windows.Media;
using
System.Windows.Media.Animation;
using
System.Windows.Shapes;
using
Telerik.Windows.Controls.Charting;
namespace
RadchartSLDemo
{
public
partial
class
MainPage : UserControl
{
List<List<ChartSampleData>> myTestData =
new
List<List<ChartSampleData>>();
public
MainPage()
{
InitializeComponent();
this
.Loaded += (s, e) =>
{
DataChartArea.EnableAnimations =
false
;
//hummm, calling RebindChart() here often causes exception in chart:
// System.NullReferenceException was unhandled by user code
//Message=Object reference not set to an instance of an object.
//StackTrace:
// at Telerik.Windows.Controls.Charting.SeriesMapping.RebindChart()
// at Telerik.Windows.Controls.Charting.SeriesMapping.ManageChangeNotifications(Object originalData, Object oldData)
// at Telerik.Windows.Controls.Charting.SeriesMapping.ItemsSourcePropertyChanged(DependencyObject target, DependencyPropertyChangedEventArgs args)
//RebindChart();
};
}
private
void
Button_Click(
object
sender, RoutedEventArgs e)
{
BusyIndicator.IsBusy =
true
;
BuildData();
RebindChart();
BusyIndicator.IsBusy =
false
;
}
protected
int
GetColor()
{
int
r = ChartSampleData.RandomInt(0, 255);
int
g = ChartSampleData.RandomInt(0, 255);
int
b = ChartSampleData.RandomInt(0, 255);
int
rgb = -1;
rgb = rgb << 8;
rgb |= r;
rgb = rgb << 8;
rgb |= g;
rgb = rgb << 8;
rgb |= b;
return
rgb;
}
protected
int
GetBins()
{
int
num = 20;
int
.TryParse(Bins.Text,
out
num);
return
num;
}
protected
int
GetStacks()
{
int
num = 20;
int
.TryParse(Stacks.Text,
out
num);
return
num;
}
protected
void
BuildData()
{ BusyIndicator.IsBusy =
true
;
myTestData.Clear();
int
count = GetBins();
int
stackCount = GetStacks();
for
(
int
i = 0; i < stackCount; i++)
{
List<ChartSampleData> data = ChartSampleData.BuildSampleData(GetColor(), count);
myTestData.Add(data);
}
}
protected
void
RebindChart()
{
DateTime st = DateTime.Now;
ClearAllChartData();
DateTime clearendtime = DateTime.Now;
PlotData<StackedBarSeriesDefinition>(DataChartArea);
DateTime et = DateTime.Now;
TimeSpan ctt = clearendtime - st;
TimeSpan plottt = et - clearendtime;
TimeSpan tt = et - st;
TimeBlock.Text = tt.ToString();
}
protected
void
ClearAllChartData()
{
ClearPlotData(DataChartArea);
}
protected
void
ClearPlotData(ChartArea chartArea)
{
if
(chartArea == DataChartArea)
{
radChart1.ItemsSource =
null
;
radChart1.SeriesMappings.Clear();
}
}
protected
void
PlotData<TSeriesDefinition>(ChartArea chartArea) where TSeriesDefinition : ISeriesDefinition,
new
()
{
DateTime st = DateTime.Now;
TimeSpan colorTT =
new
TimeSpan();
TimeSpan seriesTT =
new
TimeSpan();
if
(chartArea ==
null
|| myTestData ==
null
|| myTestData.Count == 0)
return
;
try
{
foreach
(var fs
in
myTestData)
{
List<ChartSampleData> csd = (List<ChartSampleData>)fs;
SeriesMapping sm =
new
SeriesMapping();
sm.ChartArea = chartArea;
var seriesDefintion =
new
TSeriesDefinition();
sm.SeriesDefinition = seriesDefintion;
sm.SeriesDefinition.ShowItemLabels =
false
;
sm.SeriesDefinition.LegendDisplayMode = LegendDisplayMode.DataPointLabel;
sm.SeriesDefinition.ShowItemToolTips =
true
;
sm.SeriesDefinition.ItemToolTipFormat =
"#DATAITEM.Value : #DATAITEM.Count"
;
seriesDefintion.InteractivitySettings =
new
InteractivitySettings { SelectionMode = ChartSelectionMode.Multiple, SelectionScope = InteractivityScope.Item };
DateTime cot = DateTime.Now;
int
colorAsInt = csd[0].Color;
Color c2 = Color.FromArgb((
byte
)((colorAsInt >> 0x18) & 0xff),
(
byte
)((colorAsInt >> 0x10) & 0xff),
(
byte
)((colorAsInt >> 8) & 0xff),
(
byte
)(colorAsInt & 0xff));
seriesDefintion.Appearance.Fill =
new
SolidColorBrush(c2);
DateTime coet = DateTime.Now;
TimeSpan ctt = coet - cot;
colorTT += ctt;
sm.ItemMappings.Add(
new
ItemMapping(
"Count"
, DataPointMember.YValue));
sm.ItemMappings.Add(
new
ItemMapping(
"Value"
, DataPointMember.XCategory));
sm.ItemMappings.Add(
new
ItemMapping(
"Value"
, DataPointMember.LegendLabel));
DateTime smt = DateTime.Now;
sm.ItemsSource = csd;
radChart1.SeriesMappings.Add(sm);
DateTime smet = DateTime.Now;
TimeSpan stt = smet - smt;
seriesTT += stt;
}
chartArea.AxisX.LabelRotationAngle = -45;
}
finally
{
}
DateTime et = DateTime.Now;
TimeSpan tt = et - st;
}
}
public
class
ChartSampleData
{
private
static
Random myRandom =
new
Random((
int
)DateTime.Now.Ticks);
public
static
int
RandomInt(
int
min,
int
max)
{
int
num = myRandom.Next(min, max);
if
(num < 0)
num = 0;
return
num;
}
public
static
List<ChartSampleData> BuildSampleData(Color x,
int
count)
{
int
rgb = x.A;
rgb = rgb << 8;
rgb |= x.R;
rgb = rgb << 8;
rgb |= x.G;
rgb = rgb << 8;
rgb |= x.B;
List<ChartSampleData> list =
new
List<ChartSampleData>();
for
(
int
i = 0; i < count; i++)
{
ChartSampleData sd =
new
ChartSampleData();
string
n =
""
+ i;
sd.Value = n;
//try to bias a few 0 counts
sd.Count = RandomInt(-5,20);
sd.Color = rgb;
list.Add(sd);
}
return
list;
}
public
static
List<ChartSampleData> BuildSampleData(
int
rgb,
int
count)
{
List<ChartSampleData> list =
new
List<ChartSampleData>();
for
(
int
i = 0; i < count; i++)
{
ChartSampleData sd =
new
ChartSampleData();
string
n =
""
+ i;
sd.Value = n;
sd.Count = RandomInt(-5, 20);
sd.Color = rgb;
list.Add(sd);
}
return
list;
}
public
ChartSampleData() { }
public
string
Value
{
get
;
set
;
}
public
int
Count
{
get
;
set
;
}
public
int
Color
{
get
;
set
;
}
}
}