简体   繁体   English

在WPF中使用数据绑定时,OxyPlot不会刷新

[英]OxyPlot not refreshing when using data binding in WPF

I'm asynchonrously getting data and attempting to populate a plot via the LineSeries, except the plot does not refresh when the bound collection (ObservableCollection) is updated. 我不知道如何获取数据并尝试通过LineSeries填充绘图,除非更新绑定集合(ObservableCollection)时绘图不会刷新。 Note: I have a XAML behavior to call InvalidatePlot(true) when the bound collection changes. 注意:当绑定集合发生更改时,我有一个XAML行为来调用InvalidatePlot(true)。

Can anyone explain why the plot is not updating as expected? 任何人都可以解释为什么情节不按预期更新?

WPF .Net 4.0 OxyPlot 2014.1.293.1 WPF .Net 4.0 OxyPlot 2014.1.293.1

I have the following XAML datatemplate, as you can see the LineSeries ItemsSource is bound to a property (PlotData) in the ViewModel: 我有以下XAML数据窗口,因为您可以看到LineSeries ItemsSource绑定到ViewModel中的属性(PlotData):

<DataTemplate DataType="{x:Type md:DataViewModel}">

    <Grid>

        <oxy:Plot x:Name="MarketDatePlot"
                    Margin="10">
            <oxy:Plot.Axes>
                <oxy:DateTimeAxis Position="Bottom"
                                    StringFormat="dd/MM/yy"
                                    MajorGridlineStyle="Solid"
                                    MinorGridlineStyle="Dot"
                                    IntervalType="Days"
                                    IntervalLength="80" />
                <oxy:LinearAxis Position="Left"
                                MajorGridlineStyle="Solid"
                                MinorGridlineStyle="Dot"
                                IntervalLength="100" />
            </oxy:Plot.Axes>
            <oxy:LineSeries ItemsSource="{Binding Path=PlotData, Mode=OneWay}" />
            <i:Interaction.Behaviors>
                <behaviors:OxyPlotBehavior ItemsSource="{Binding Path=PlotData, Mode=OneWay}" />
            </i:Interaction.Behaviors>
        </oxy:Plot>
    </Grid>

</DataTemplate>

As I said the ViewModel requests and populates the bound collection asynchronously (the actual population of bound collection happens on the UI thread): 正如我所说,ViewModel以异步方式请求和填充绑定集合(绑定集合的实际填充发生在UI线程上):

public sealed class DataViewModel : BaseViewModel, IDataViewModel
{
    private readonly CompositeDisposable _disposable;
    private readonly CancellationTokenSource _cancellationTokenSource;
    private readonly RangeObservableCollection<DataPoint> _plotData;

    public DataViewModel(DateTime fromDate, DateTime toDate, IMarketDataService marketDataService, ISchedulerService schedulerService)
    {
        _plotData = new RangeObservableCollection<DataPoint>();
        _disposable = new CompositeDisposable();

        if (fromDate == toDate)
        {
            // nothing to do...
            return;
        }

        _cancellationTokenSource = new CancellationTokenSource();

        _disposable.Add(Disposable.Create(() =>
        {
            if (!_cancellationTokenSource.IsCancellationRequested)
            {
                _cancellationTokenSource.Cancel();
            }
        }));

        marketDataService.GetDataAsync(fromDate, toDate)
            .ContinueWith(t =>
            {
                if (t.IsFaulted)
                {
                    throw new Exception("Failed to get market data!", TaskHelper.GetFirstException(t));
                }

                return t.Result.Select(x => new DataPoint(DateTimeAxis.ToDouble(x.Time), x.Value));
            }, schedulerService.Task.Default)
            .SafeContinueWith(t => _plotData.AddRange(t.Result), schedulerService.Task.CurrentSynchronizationContext);
    }

    public void Dispose()
    {
        _disposable.Dispose();
    }

    public IEnumerable<DataPoint> PlotData
    {
        get { return _plotData; }
    }
}

And the XAML behavior looks like this: 并且XAML行为如下所示:

(I can't seem to paste in anymore code, SO keeps throwing an error on save) (我似乎无法粘贴任何代码,因此在保存时不断抛出错误)

OxyPlot does not automatically update when you add data. 添加数据时,OxyPlot不会自动更新。

You must call plotname.InvalidatePlot(true); 你必须调用plotname.InvalidatePlot(true);

and it must run on the UI dispatcher thread, ie 它必须在UI调度程序线程上运行,即

Dispatcher.InvokeAsync(() => 
{
    plotname.InvalidatePlot(true);
}

Don't know if people still need this but I was having the same problems with itemsource not updating chart. 不知道人们是否仍然需要这个但是我遇到了与itemsource没有更新图表相同的问题。 And none of the existing solutions helped me. 现有的解决方案都没有帮助我。

Well I've finally found the reason why whole thing didn't work. 好吧,我终于找到了整个事情无效的原因。 I've assigned my collection to itemsource before I actually initialized it (new Observable....). 在我实际初始化之前,我已将我的集合分配给itemsource(新的Observable ....)。

When i tried assigning already initialized collection to my itemsource, whole thing started working. 当我尝试将已经初始化的集合分配给我的itemsource时,整个事情开始起作用。

Hope this helps someone. 希望这有助于某人。

I know this is an old question but maybe someone will use my answer after hours of double checking. 我知道这是一个古老的问题,但也许有人会在经过数小时的双重检查后使用我的答案。 I use MVVM. 我使用MVVM。 I'm updating the data with await Task.Run(()=> update()); 我正在使用等待Task.Run(()=> update())来更新数据; and that wasn't rendering my plot in my UI. 那并没有在我的UI中呈现我的情节。 I was also initializing my PlotModel before setting it. 我在设置它之前也在初始化我的PlotModel。 Turns out, initializing the PlotModel in that update() method wasn't registering in my UI. 事实证明,初始化该update()方法中的PlotModel并没有在我的UI中注册。 I had to initialize it before I called that Task to run. 在调用Task运行之前,我不得不初始化它。

public ViewModel()
{
     Plot = new PlotModel(); //(Plot is a property using 
                             // INotifyPropertyChanged)
     PlotGraph = new RelayCommand(OnPlotGraph);
}

public RelayCommand PlotGraph {get; set;}

private async void OnPlotGraph()
{
     await Task.Run(() => Update());
}

private void Update()
{
    var tempPlot = new PlotModel();
    //(set up tempPlot, add data to tempPlot)
    Plot = tempPlot;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM