Hi
Very odd situation. I have a simple line chart (see code below) which has e.g. 100 data points. I'm using XValue on the X axis and doing ranging myself (AutoRange=false). The X values are integers but I manually override the string values for the TickPoints' Label with the actual strings I need to display for each (in general the strings cannot be determined using a format pattern). In the chart's SizeChanged event I recalculate the Step/LabelStep/MinorTickPointMultiplier etc. values each time so that things are spaced nicely (only the Step part of the calculation is shown below).
Now, if there aren't too many data points then it works perfectly and the Label string values are always shown.
But once I exceed say 70 data points, then as I resize the form slowly (to check that it's Step calculations look OK all the way) sometimes the Label values are shown (attached image 1) and sometimes the underlying TickPoint.Value number is shown instead (image 2). It seems at some specific points it flips from the one to the other (repeatably). I checked via a breakpoint and the Labels are always getting set. It is, as if the Tick Points are being reset again afterwards.
I just cannot figure out what else is happening behind the scenes....
Here's a small example that demonstrates (just create a WPF form with a chart and attach chart's SizeChanged event)
Very odd situation. I have a simple line chart (see code below) which has e.g. 100 data points. I'm using XValue on the X axis and doing ranging myself (AutoRange=false). The X values are integers but I manually override the string values for the TickPoints' Label with the actual strings I need to display for each (in general the strings cannot be determined using a format pattern). In the chart's SizeChanged event I recalculate the Step/LabelStep/MinorTickPointMultiplier etc. values each time so that things are spaced nicely (only the Step part of the calculation is shown below).
Now, if there aren't too many data points then it works perfectly and the Label string values are always shown.
But once I exceed say 70 data points, then as I resize the form slowly (to check that it's Step calculations look OK all the way) sometimes the Label values are shown (attached image 1) and sometimes the underlying TickPoint.Value number is shown instead (image 2). It seems at some specific points it flips from the one to the other (repeatably). I checked via a breakpoint and the Labels are always getting set. It is, as if the Tick Points are being reset again afterwards.
I just cannot figure out what else is happening behind the scenes....
Here's a small example that demonstrates (just create a WPF form with a chart and attach chart's SizeChanged event)
private
void
SetupChart()
{
// some data to visualise...
// NB: need a reasonable number of points, doesn't exhibit at low numbers
var data =
new
DataTable();
data.Columns.Add(
"x"
,
typeof
(
int
));
data.Columns.Add(
"y"
,
typeof
(
double
));
var date =
new
DateTime(2012, 1, 1);
var rnd =
new
Random();
for
(var i = 0; i < 100; i++)
{
var row = data.NewRow();
row[
"x"
] = date.Year * 12 + date.Month - 1;
// integer value calc'd so that 1st of month is evenly spaced (see UpdateLabels() below)
row[
"y"
] = 50 + rnd.NextDouble() * 10;
data.Rows.Add(row);
date = date.AddMonths(1);
}
// just set up a basic line chart for testing purposes...
chart.DefaultView.ChartLegend.Visibility = System.Windows.Visibility.Collapsed;
chart.DefaultView.ChartArea.EnableAnimations =
false
;
chart.DefaultView.ChartArea.AxisY.StripLinesVisibility = System.Windows.Visibility.Collapsed;
chart.DefaultView.ChartArea.AxisX =
new
AxisX();
chart.DefaultView.ChartArea.AxisX.LayoutMode = AxisLayoutMode.Auto;
chart.DefaultView.ChartArea.AxisX.StripLinesVisibility = System.Windows.Visibility.Collapsed;
chart.DefaultView.ChartArea.AxisX.AutoRange =
false
;
chart.DefaultView.ChartArea.AxisX.MinValue = data.Rows.Cast<DataRow>().Min(r => (
int
)r[
"x"
]);
chart.DefaultView.ChartArea.AxisX.MaxValue = data.Rows.Cast<DataRow>().Max(r => (
int
)r[
"x"
]);
var mapping =
new
SeriesMapping();
mapping.ItemsSource = data;
mapping.ItemMappings.Add(
new
ItemMapping(
"x"
, DataPointMember.XValue) { FieldType = data.Columns[
"x"
].DataType });
mapping.ItemMappings.Add(
new
ItemMapping(
"y"
, DataPointMember.YValue) { FieldType = data.Columns[
"y"
].DataType });
mapping.SeriesDefinition =
new
LineSeriesDefinition();
chart.SeriesMappings.Add(mapping);
// to force initial ranging calc to occur...
chart_SizeChanged(
null
,
null
);
}
/// <summary>
/// Event handler
/// </summary>
private
void
chart_SizeChanged(
object
sender, SizeChangedEventArgs e)
{
if
(e ==
null
|| e.WidthChanged)
{
RecalcRange();
UpdateLabels();
}
}
/// <summary>
/// Event handler
/// </summary>
private
void
updateLabelsButton_Click(
object
sender, RoutedEventArgs e)
{
// manual force recalculate of the labels
UpdateLabels();
}
private
void
RecalcRange()
{
#if true
// pick a reasonable step value...
var width = chart.DefaultView.ChartArea.ActualWidth;
var range = chart.DefaultView.ChartArea.AxisX.MaxValue - chart.DefaultView.ChartArea.AxisX.MinValue;
var step = Math.Max(1, (
int
)Math.Ceiling(range * chart.DefaultView.ChartArea.AxisX.TicksDistance / width));
chart.DefaultView.ChartArea.AxisX.Step = step;
#else
// it happens for certain constants, such as 8 (but not for 9 etc)...
chart.DefaultView.ChartArea.AxisX.Step = 8;
#endif
}
private
void
UpdateLabels()
{
foreach
(var tickPoint
in
chart.DefaultView.ChartArea.AxisX.TickPoints)
{
// Reconstitutes the date string for the label from the integer value in x column..
var dt =
new
DateTime((
int
)tickPoint.Value / 12, ((
int
)tickPoint.Value % 12) + 1, 1);
tickPoint.Label = dt.ToString(
"MMM-yy"
);
}
}