The following example shows how to plot an XY series with a histogram in the same chart:
In this example, a Line series displays a normal distribution curve on the secondary axis and is aligned with a histogram on the primary axis.
View Example: How to: Plot an XY Series with a Histogram in a Chart
using System;
using System.Collections.ObjectModel;
using System.Windows;
namespace SideBySideBar2DChart {
public partial class Window1 : Window {
public Window1() {
InitializeComponent();
}
}
public class ViewModel {
const int HistogramPointsCount = 1000;
const int DistributionPointsCount = 100;
const double Mean = 0.5;
const double StdDev = 0.15;
const double Max = 10;
Random random = new Random();
public ObservableCollection<DataPoint> NormalDistribution { get; private set; }
public ObservableCollection<DataPoint> Histogram { get; private set; }
public double MinValue { get { return 0; } }
public double MaxValue { get { return Max; } }
public double BinCount { get { return 20; } }
public ViewModel() {
CreateDataSource();
}
void CreateDataSource() {
NormalDistribution = new ObservableCollection<DataPoint>();
for(int i = 0; i < DistributionPointsCount; i++) {
double x = i * Max / DistributionPointsCount;
NormalDistribution.Add(new DataPoint(x, GetNormalDistribution(x, Mean * Max, StdDev * Max)));
}
Histogram = new ObservableCollection<DataPoint>();
for(int x = 0; x < HistogramPointsCount; x++)
Histogram.Add(new DataPoint(GenerateHistogramPoint(Mean * Max, StdDev * Max)));
}
double GetNormalDistribution(double x, double mean, double stdDev) {
double tmp = 1 / (Math.Sqrt(2 * Math.PI) * stdDev);
return Math.Exp(-Math.Pow(x - mean, 2) / (2 * Math.Pow(stdDev, 2))) * tmp;
}
double GenerateHistogramPoint(double mean, double stdDev) {
return Math.Sqrt(-2 * Math.Log(random.NextDouble())) * Math.Cos(2 * Math.PI * random.NextDouble()) * stdDev + mean;
}
}
}
Imports System
Imports System.Collections.ObjectModel
Imports System.Windows
Namespace SideBySideBar2DChart
Public Partial Class Window1
Inherits Window
Public Sub New()
Me.InitializeComponent()
End Sub
End Class
Public Class ViewModel
Private _NormalDistribution As ObservableCollection(Of SideBySideBar2DChart.DataPoint), _Histogram As ObservableCollection(Of SideBySideBar2DChart.DataPoint)
Const HistogramPointsCount As Integer = 1000
Const DistributionPointsCount As Integer = 100
Const Mean As Double = 0.5
Const StdDev As Double = 0.15
Const Max As Double = 10
Private random As Random = New Random()
Public Property NormalDistribution As ObservableCollection(Of DataPoint)
Get
Return _NormalDistribution
End Get
Private Set(ByVal value As ObservableCollection(Of DataPoint))
_NormalDistribution = value
End Set
End Property
Public Property Histogram As ObservableCollection(Of DataPoint)
Get
Return _Histogram
End Get
Private Set(ByVal value As ObservableCollection(Of DataPoint))
_Histogram = value
End Set
End Property
Public ReadOnly Property MinValue As Double
Get
Return 0
End Get
End Property
Public ReadOnly Property MaxValue As Double
Get
Return Max
End Get
End Property
Public ReadOnly Property BinCount As Double
Get
Return 20
End Get
End Property
Public Sub New()
CreateDataSource()
End Sub
Private Sub CreateDataSource()
NormalDistribution = New ObservableCollection(Of DataPoint)()
For i As Integer = 0 To DistributionPointsCount - 1
Dim x As Double = i * Max / DistributionPointsCount
NormalDistribution.Add(New DataPoint(x, GetNormalDistribution(x, Mean * Max, StdDev * Max)))
Next
Histogram = New ObservableCollection(Of DataPoint)()
For x As Integer = 0 To HistogramPointsCount - 1
Histogram.Add(New DataPoint(GenerateHistogramPoint(Mean * Max, StdDev * Max)))
Next
End Sub
Private Function GetNormalDistribution(ByVal x As Double, ByVal mean As Double, ByVal stdDev As Double) As Double
Dim tmp As Double = 1 / (Math.Sqrt(2 * Math.PI) * stdDev)
Return Math.Exp(-Math.Pow(x - mean, 2) / (2 * Math.Pow(stdDev, 2))) * tmp
End Function
Private Function GenerateHistogramPoint(ByVal mean As Double, ByVal stdDev As Double) As Double
Return Math.Sqrt(-2 * Math.Log(random.NextDouble())) * Math.Cos(2 * Math.PI * random.NextDouble()) * stdDev + mean
End Function
End Class
End Namespace
<Window
x:Class="SideBySideBar2DChart.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dxc="http://schemas.devexpress.com/winfx/2008/xaml/charts"
xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm"
xmlns:local="clr-namespace:SideBySideBar2DChart"
Width="820.806"
Height="354.032"
DataContext="{dxmvvm:ViewModelSource Type=local:ViewModel}"
Title="WPF Chart">
<Grid>
<dxc:ChartControl Name="chartControl1">
<dxc:ChartControl.Diagram>
<dxc:XYDiagram2D x:Name="diagram">
<dxc:XYDiagram2D.AxisX>
<dxc:AxisX2D Name="primaryAxisX" Visible="True">
<dxc:AxisX2D.WholeRange>
<dxc:Range
MaxValue="{Binding MaxValue}"
MinValue="{Binding MinValue}"
SideMarginsValue="0" />
</dxc:AxisX2D.WholeRange>
<dxc:AxisX2D.NumericScaleOptions>
<dxc:CountIntervalNumericScaleOptions
Count="{Binding BinCount}"
GridLayoutMode="GridShiftedLabelCentered"
Pattern="{}{OB}{A1:F1}, {A2:F1}{CB}" />
</dxc:AxisX2D.NumericScaleOptions>
</dxc:AxisX2D>
</dxc:XYDiagram2D.AxisX>
<dxc:XYDiagram2D.SecondaryAxesX>
<dxc:SecondaryAxisX2D Name="secondaryAxisX" Visible="False">
<dxc:SecondaryAxisX2D.NumericScaleOptions>
<dxc:ContinuousNumericScaleOptions />
</dxc:SecondaryAxisX2D.NumericScaleOptions>
<dxc:SecondaryAxisX2D.WholeRange>
<dxc:Range SideMarginsValue="0" />
</dxc:SecondaryAxisX2D.WholeRange>
</dxc:SecondaryAxisX2D>
</dxc:XYDiagram2D.SecondaryAxesX>
<dxc:XYDiagram2D.SecondaryAxesY>
<dxc:SecondaryAxisY2D Name="secondaryAxisY" />
</dxc:XYDiagram2D.SecondaryAxesY>
<dxc:XYDiagram2D.Series>
<dxc:BarStackedSeries2D
AggregateFunction="Histogram"
ArgumentDataMember = "XValue"
ArgumentScaleType="Numerical"
BarWidth="1"
DataSource="{Binding Histogram}"
DisplayName="Histogram" />
<dxc:SplineSeries2D
AggregateFunction="None"
ArgumentDataMember = "XValue"
ArgumentScaleType="Numerical"
AxisX="{Binding ElementName=secondaryAxisX}"
AxisY="{Binding ElementName=secondaryAxisY}"
DataSource="{Binding NormalDistribution}"
DisplayName="Normal Distribution"
ValueDataMember = "YValue" />
</dxc:XYDiagram2D.Series>
</dxc:XYDiagram2D>
</dxc:ChartControl.Diagram>
</dxc:ChartControl>
</Grid>
</Window>
See Also