I want to define a HighLowSeries
via XAML. Since HighLowSeries-graphs
are not available in the oxyplot.wpf
namespace I've created the following class:
public class HighLowSeries : OxyPlot.Wpf.XYAxisSeries
{
public HighLowSeries()
{
this.InternalSeries = new OxyPlot.Series.HighLowSeries();
}
public override OxyPlot.Series.Series CreateModel()
{
this.SynchronizeProperties(this.InternalSeries);
return this.InternalSeries;
}
/// <summary>
/// The synchronize properties.
/// </summary>
/// <param name="series">
/// The series.
/// </param>
protected override void SynchronizeProperties(OxyPlot.Series.Series series)
{
base.SynchronizeProperties(series);
var s = (OxyPlot.Series.HighLowSeries)series;
foreach (HighLowItem item in s.Items)
{
Trace.WriteLine("HighLowSeries " + item.X);
}
}
}
In my Window, I use the HighLowSeries
the following way:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Oxy="http://oxyplot.org/wpf"
xmlns:Tmp="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Oxy:PlotView Width="300"
Height="300"
Title="Test">
<Oxy:PlotView.Series>
<Tmp:HighLowSeries ItemsSource="{Binding list}" />
</Oxy:PlotView.Series>
</Oxy:PlotView>
</Grid>
</Window>
In the code behind of the Window, I have the following code:
private IList<HighLowItem> _list;
public IList<HighLowItem> list
{
get
{
return this._list;
}
set
{
this._list = value;
}
}
public MainWindow()
{
this.list = new List<HighLowItem>();
list.Add(new HighLowItem(10, 8, 3, 2, 5));
list.Add(new HighLowItem(12, 7, 4, 4, 2));
list.Add(new HighLowItem(18, 4, 1, 2, 3));
this.DataContext = this;
InitializeComponent();
}
When I start the application there is only a tiny horizontal line at (0,0):
Additionally there is a Trace.WriteLine
in HighLowSeries.SynchronizeProperties()
where I print out the X-coordinates of the HighLowElements
in the Items-Collection. The quantity of outputs matches the elements in the list-property of MainWindow
. But the X-coordinate is always 0 (as well as the other properties of the HighLowElements
).
When I implement my own LineSeries
the same way, everything works as it should.
Is this a bug in oxyplot? Or am I missing anything? Creating the HighLowSeries
via code is not an option at the moment.
Finally found the spot, where the list with DataPoints
is cleared.
In the source code (OxyPlot Source HighLowItemSeries)
There is this method:
/// <summary>
/// Updates the data.
/// </summary>
protected internal override void UpdateData()
{
if (this.ItemsSource == null)
{
return;
}
this.items.Clear();
// Use the mapping to generate the points
if (this.Mapping != null)
{
foreach (var item in this.ItemsSource)
{
this.items.Add(this.Mapping(item));
}
return;
}
var filler = new ListFiller<HighLowItem>();
filler.Add(this.DataFieldX, (p, v) => p.X = Axis.ToDouble(v));
filler.Add(this.DataFieldHigh, (p, v) => p.High = Axis.ToDouble(v));
filler.Add(this.DataFieldLow, (p, v) => p.Low = Axis.ToDouble(v));
filler.Add(this.DataFieldOpen, (p, v) => p.Open = Axis.ToDouble(v));
filler.Add(this.DataFieldClose, (p, v) => p.Close = Axis.ToDouble(v));
filler.FillT(this.items, this.ItemsSource);
}
Since this.Mapping
equals null, the mapping
is bypassed and a filler object
is added.
The comment of the Mapping-field
says how to set the value:
/// <summary>
/// Gets or sets the mapping delegate.
/// </summary>
/// <value>The mapping.</value>
/// <remarks>Example: series1.Mapping = item => new HighLowItem(((MyType)item).Time,((MyType)item).Value);</remarks>
public Func<object, HighLowItem> Mapping { get; set; }
If I change the SynchronizeProperties
method to the following everything works as it should.
protected override void SynchronizeProperties(OxyPlot.Series.Series series)
{
base.SynchronizeProperties(series);
var s = (OxyPlot.Series.HighLowSeries)series;
s.Mapping = item => new HighLowItem(((HighLowItem)item).X, ((HighLowItem)item).High, ((HighLowItem)item).Low, ((HighLowItem)item).Open, ((HighLowItem)item).Close);
}