我想在WPF中绘制类似示波器的动态折线图,我发现这个库:Interactive Data Display来自这个库:D3 Dynamic Data Display。它的优点是它对我来说很重要。
从示例程序中,我可以看到它们没有将LineGraph.Points绑定到任何集合,当我尝试它不起作用时,Graph对象上也没有Refresh或Update方法。目前,我每次想要更新图表时都被迫使用LineGraph.PlotY()
方法。
有人知道是否有可能以MVVM的方式使用这个库?
示例代码:
double[] x = new double[200];
for (int i = 0; i < x.Length; i++)
x[i] = 3.1415 * i / (x.Length - 1);
for (int i = 0; i < 25; i++)
{
var lg = new LineGraph();
lines.Children.Add(lg);
lg.Stroke = new SolidColorBrush(Color.FromArgb(255, 0, (byte)(i * 10), 0));
lg.Description = String.Format("Data series {0}", i + 1);
lg.StrokeThickness = 2;
lg.Plot(x, x.Select(v => Math.Sin(v + i / 10.0)).ToArray());
}
XAML:
<d3:Chart Name="plotter">
<d3:Chart.Title>
<TextBlock HorizontalAlignment="Center" FontSize="18" Margin="0,5,0,5">Line graph legend sample</TextBlock>
</d3:Chart.Title>
<d3:Chart.LegendContent>
<d3:LegendItemsPanel>
<d3:LegendItemsPanel.Resources>
<DataTemplate x:Key="InteractiveDataDisplay.WPF.LineGraph">
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding Path=Visibility, Converter={StaticResource VisibilityToCheckedConverter}, Mode=TwoWay}"/>
<Line Width="15" Height="15" X1="0" Y1="0" X2="15" Y2="15" Stroke="{Binding Path=Stroke}" StrokeThickness="2"/>
<TextBlock Margin="5,0,0,0" Text="{Binding Path=Description}"/>
</StackPanel>
</DataTemplate>
</d3:LegendItemsPanel.Resources>
</d3:LegendItemsPanel>
</d3:Chart.LegendContent>
<Grid Name="lines"/>
</d3:Chart>
答案 0 :(得分:1)
在Plot
基类中,已经为Points
属性注册了依赖项属性。作为快速解决方法,我将其添加到LineGraph
类:
public ObservableCollection<Point> ObservablePoints
{
get { return (ObservableCollection<Point>)GetValue(ObservablePointsProperty); }
set { SetValue(ObservablePointsProperty, value); }
}
public static readonly DependencyProperty ObservablePointsProperty =
DependencyProperty.RegisterAttached(
"ObservablePoints",
typeof(ObservableCollection<Point>),
typeof(LineGraph),
new PropertyMetadata(
new ObservableCollection<Point>(),
(d, e) =>
{
var linePlot = (LineGraph)d;
var updateAction = new NotifyCollectionChangedEventHandler(
(o, args) =>
{
if (linePlot != null)
{
InteractiveDataDisplay.WPF.Plot.SetPoints(linePlot.polyline, new PointCollection((ObservableCollection<Point>)o));
}
});
if (e.OldValue != null)
{
var coll = (INotifyCollectionChanged)e.OldValue;
coll.CollectionChanged -= updateAction;
}
if (e.NewValue != null)
{
var coll = (INotifyCollectionChanged)e.NewValue;
coll.CollectionChanged += updateAction;
if (linePlot != null)
{
InteractiveDataDisplay.WPF.Plot.SetPoints(linePlot.polyline, new PointCollection((ObservableCollection<Point>)e.NewValue));
}
}
}));
然后,将我的点集合绑定到ObservablePoints
属性:
<d3:LineGraph Description="MyGraph"
ObservablePoints="{Binding Path=PointsFromMyDatamodel}"/>
缺点是重绘了所有点的图表 - 因此快速修复了#39;仅重绘已添加,修改或删除的点将需要对底层基类进行更多更改...