|
Multiple XYCharts in one MultiChart |
Posted by Philip on Oct-08-2020 03:00 |
|
Hello Peter,
I have been experimenting with the example RealTimeZoomScrollWindow. It shows an XYChart with three lines (Alpha, Beta and Gamma).
In the GUI I added a checkbox called "separate". My intention was to toggle between one XYChart showing 3 lines with 3 stacked XYCharts each showing 1 line. For stacked XYCharts I have to create a MultiChart and then add each XYChart to the MultiChart.
I renamed the existing drawChart() to drawMyChart(). Then I created a new drawChart():
private void drawChart(WPFChartViewer viewer)
{
// dimensions of a XYChart
int widthOfXyChart = 640;
int heightOfXyChart = 350;
if (separate.IsChecked == false)
{
// XYChart will contain 3 lines
drawMyChart(viewer, widthOfXyChart, heightOfXyChart, -1, null);
}
else
{
int numberOfCharts = 3;
// multi-chart will contain 3 XYCharts
int widthOfMultiChart = widthOfXyChart;
int heightOfMultiChart = heightOfXyChart * numberOfCharts;
MultiChart mc = new MultiChart(widthOfMultiChart, heightOfMultiChart);
viewer.Chart = mc;
for (int i = 1; i <= numberOfCharts; i++)
{
drawMyChart(viewer, widthOfXyChart, heightOfXyChart, i, mc);
}
}
}
private void drawMyChart(WPFChartViewer viewer, int widthOfXyChart, int heightOfXyChart, int lineId, MultiChart mc)
{
// Get the start date and end date that are visible on the chart.
...
// Extract the part of the data arrays that are visible.
...
//
// At this stage, we have extracted the visible data. We can use those data to plot the chart.
//
//=======================
// Configure overall chart appearance.
//=======================
// Create an XYChart object of size 640 x 350 pixels
XYChart c = new XYChart(widthOfXyChart, heightOfXyChart);
...
//===========
// Add data to chart
//===========
//
// In this example, we represent the data by lines. You may modify the code below to use other
// representations (areas, scatter plot, etc).
//
// Add a line layer for the lines, using a line width of 2 pixels
LineLayer layer = c.addLineLayer2();
layer.setLineWidth(2);
layer.setFastLineMode();
// Now we add the 3 data series to a line layer, using the color red (ff0000), green (00cc00)
// and blue (0000ff)
if (separate.IsChecked == false)
{
// lines grouped in one XYChart
layer.setXData(viewPortTimeStamps);
// check to see if lines are displayed
if (checkboxA.IsChecked == true)
layer.addDataSet(viewPortDataSeriesA, 0xff0000, "Alpha");
if (checkboxB.IsChecked == true)
layer.addDataSet(viewPortDataSeriesB, 0x00cc00, "Beta");
if (checkboxC.IsChecked == true)
layer.addDataSet(viewPortDataSeriesC, 0x0000ff, "Gamma");
}
else
{
// one line per XYChart
layer.setXData(viewPortTimeStamps);
if (lineId == 1)
layer.addDataSet(viewPortDataSeriesA, 0xff0000, "Alpha");
else if (lineId == 2)
layer.addDataSet(viewPortDataSeriesB, 0x00cc00, "Beta");
else if (lineId == 3)
layer.addDataSet(viewPortDataSeriesC, 0x0000ff, "Gamma");
}
//=====================
// Configure axis scale and labelling
//=====================
...
//=====================
// Output the chart
//=====================
// We need to update the track line too. If the mouse is moving on the chart (eg. if
// the user drags the mouse on the chart to scroll it), the track line will be updated
// in the MouseMovePlotArea event. Otherwise, we need to update the track line here.
if (!viewer.IsInMouseMoveEvent)
{
trackLineLabel(c, (null == viewer.Chart) ? c.getPlotArea().getRightX() :
viewer.PlotAreaMouseX);
}
if (separate.IsChecked == false)
{
// all lines in one XYChart
viewer.Chart = c;
}
else
{
// one line per XYChart
// calculate top-left x,y coordinates within multi-chart. XYCharts are stacked vertically
int xCoordinate = 0;
int yCoordinate = (lineId - 1) * heightOfXyChart; // values will be 0 * 350, 1 * 350, 2 * 350
// add XYChart to MultiChart
mc.addChart(xCoordinate, yCoordinate, c);
}
}
When I start the application I see the XYChart with 3 lines. When I checkbox "Separate", drawChart() executes this code:
MultiChart mc = new MultiChart(widthOfMultiChart, heightOfMultiChart);
viewer.Chart = mc;
and I get the exception:
System.InvalidCastException
HResult=0x80004002
Message=Unable to cast object of type 'ChartDirector.MultiChart' to type 'ChartDirector.XYChart'.
Source=CSharpWPFCharts
StackTrace:
at CSharpWPFCharts.RealTimeZoomScrollWindow.WPFChartViewer1_MouseMovePlotArea(Object sender, MouseEventArgs e) in C:Usersphilip.watkinsonsourcereposChartDirectorNetWPFChartsCSharpWPFChartsRealTimeZoomScrollWindow.xaml.cs:line 575
Here is the method:
private void WPFChartViewer1_MouseMovePlotArea(object sender, MouseEventArgs e)
{
var viewer = sender as WPFChartViewer;
trackLineLabel((XYChart)viewer.Chart, viewer.PlotAreaMouseX);
viewer.updateDisplay();
}
In the method, viewer.Chart is cast to XYChart but in my code viewer.Chart is of type MultiChart in drawChart().
What should I do?
Philip |
Re: Multiple XYCharts in one MultiChart |
Posted by Philip on Oct-08-2020 03:30 |
|
Peter,
I was able to fix the exception by modifying WPFChartViewer1_MouseMovePlotArea():
private void WPFChartViewer1_MouseMovePlotArea(object sender, MouseEventArgs e)
{
var viewer = sender as WPFChartViewer;
if (viewer.Chart.GetType() == typeof(MultiChart))
{
MultiChart mc = (MultiChart)viewer.Chart;
int numCharts = mc.getChartCount();
for (int i = 0; i < numCharts; i++)
{
trackLineLabel((XYChart)mc.getChart(i), viewer.PlotAreaMouseX);
}
}
else
{
trackLineLabel((XYChart)viewer.Chart, viewer.PlotAreaMouseX);
}
viewer.updateDisplay();
}
Unfortunately I don't see the 3 stacked XYCharts. Any idea what the problem is?
Philip |
Re: Multiple XYCharts in one MultiChart |
Posted by Peter Kwan on Oct-08-2020 13:03 |
|
Hi Philip,
For a MultiChart, when drawing the track cursor, it needs to be drawn on the dynamic layer of the MultiChart. That means we need to ask the XYChart to draw on the MultiChart dynamic layer.
There are some examples in this forum, but I cannot find one in WPF. So I just modified the WPF "Real Time Chart with Zooming and Scrolling" sample code to provide an example.
There are many styles of stacked chart. The style I use is to omit the x-axis for all charts except the bottom chart. (Sometimes people will put the x-axis at the top of the first chart as well, or to include x-axis for every chart.) I have attached the screen shot and the code for your reference.
Regards
Peter Kwan
|
|