使用外部数据使用WPF进行实时绘图

时间:2013-06-05 19:05:00

标签: c# wpf real-time system.reactive dynamic-data-display

我正在创建一个实时WPF图形绘图仪,它将在收到数据点时绘制。它利用动态数据显示库。 (http://dynamicdatadisplay.codeplex.com/

目前,应用程序已设置为:

  • 每次对我在WPF应用程序中实例化的ObservableCollection进行更改时,都会更新图形绘图仪。

  • 使用名为AddDataPoint(...)的自定义方法添加数据点,该方法修改ObservableCollection。

应用程序在环境中按预期运行(当我按F5调试我的解决方案时),但这只是因为我传入“假”数据点来测试应用程序。我利用内部的DispatchTimer / Random.Next(..)不断地将生成的数据点提供给内部实例化的ObservableCollection;但是,我不知道如何允许外部类或外部数据源输入要绘制的“真实”数据。

我对WPF和C#一般都很陌生,所以虽然我确实做了很多关于这个主题的Google,但我找不到具体的答案(即数据绑定 - 在我看来它是仅适用于应用程序内)。在将实时数据从外部源传递到我的WPF应用程序时,我陷入困境。

我尝试将WPF的.exe文件作为资源添加到外部类/解决方案中,该类将提供数据并使用以下命令启动WPF实例:

      "WPFAppNameSpace".MainWindow w = new "WPFAppNameSpace".MainWindow();  
      w.Show();
      w.AddDataPoint(...);

但是,它没有用。窗户甚至没有出现!我可以将外部类(不是WPF应用程序)传递给我的WPF图形应用程序吗?如果是这样,我该怎么做呢?我应该研究什么?

以下是我的项目中的一些代码片段:
XAML

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d3="http://research.microsoft.com/DynamicDataDisplay/1.0"
        Title="MainWindow" Height="480" Width="660" Loaded="Window_Loaded" WindowState="Maximized">
    <Grid>     
        <d3:ChartPlotter Name="plotter" Margin="12,10,12,14">

            <d3:ChartPlotter.MainHorizontalAxis>
                <d3:HorizontalAxis Name="xAxis"></d3:HorizontalAxis>
            </d3:ChartPlotter.MainHorizontalAxis>

            <d3:ChartPlotter.MainVerticalAxis>
                <d3:VerticalAxis Name="yAxis"></d3:VerticalAxis>
            </d3:ChartPlotter.MainVerticalAxis>

            <d3:VerticalAxisTitle Content="Voltage"/>
            <d3:HorizontalAxisTitle Content="Test Identifier"/>
            <d3:Header TextBlock.FontSize="20" Content="Dynamically Updated Graph"/>

        </d3:ChartPlotter>

    </Grid>

</Window>

<Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d3="http://research.microsoft.com/DynamicDataDisplay/1.0" Title="MainWindow" Height="480" Width="660" Loaded="Window_Loaded" WindowState="Maximized"> <Grid> <d3:ChartPlotter Name="plotter" Margin="12,10,12,14"> <d3:ChartPlotter.MainHorizontalAxis> <d3:HorizontalAxis Name="xAxis"></d3:HorizontalAxis> </d3:ChartPlotter.MainHorizontalAxis> <d3:ChartPlotter.MainVerticalAxis> <d3:VerticalAxis Name="yAxis"></d3:VerticalAxis> </d3:ChartPlotter.MainVerticalAxis> <d3:VerticalAxisTitle Content="Voltage"/> <d3:HorizontalAxisTitle Content="Test Identifier"/> <d3:Header TextBlock.FontSize="20" Content="Dynamically Updated Graph"/> </d3:ChartPlotter> </Grid> </Window> MainWindow.xaml.cs

1 个答案:

答案 0 :(得分:1)

作为Reactive Extensions的示例,这是一个通过模拟以0到5秒之间的随机间隔获取数据的类

public class DataAquisitionSimulator:IObservable<int>
{
    private static readonly Random RealTimeMarketData = new Random();
    public IDisposable Subscribe(IObserver<int> observer)
    {
        for (int i = 0; i < 10; i++)
        {
            int data = RealTimeMarketData.Next();
            observer.OnNext(data);
            Thread.Sleep(RealTimeMarketData.Next(5000));
        }
        observer.OnCompleted();
        return Disposable.Create(() => Console.WriteLine("cleaning up goes here"));
    }
}

它模拟获取市场数据(在这种情况下只是随机整数)并将它们发布给观察者。它在观察之间睡了一会儿,以模拟市场潜伏期。

这是一个被设置为消费者的骨骼类......

public class DataConsumer : IObserver<int>
{
    private readonly IDisposable _disposable;
    public DataConsumer(DataAquisitionSimulator das)
    {
        _disposable = das.Subscribe(this);
        _disposable.Dispose();
    }
    public void OnCompleted()
    {
        Console.WriteLine("all done");
    }
    public void OnError(Exception error)
    {
        throw error;
    }
    public void OnNext(int value)
    {
        Console.WriteLine("New data " + value + " at " + DateTime.Now.ToLongTimeString());
    }
}

它实现了所需的三种方法,并注意每次出现新数据时都会调用'OnNext'。据推测,这个类将在您的VM中实现,并立即将新数据插入到绑定管道中,以便用户可以将其可视化。

要查看这两个类的交互,可以将其添加到控制台应用程序...

static void Main(string[] args)
{
    DataAquisitionSimulator v = new DataAquisitionSimulator();
    DataConsumer c = new DataConsumer(v);
}

设计线程是关键,但除此之外,这是一个如何以结构化方式捕获具有延迟和不规则观察的外部数据的示例。