OxyPlot not refreshing when using data binding in WPF

我们两清 提交于 2019-12-22 11:30:42

问题


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. Note: I have a XAML behavior to call InvalidatePlot(true) when the bound collection changes.

Can anyone explain why the plot is not updating as expected?

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:

<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):

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:

(I can't seem to paste in anymore code, SO keeps throwing an error on save)


回答1:


OxyPlot does not automatically update when you add data.

You must call plotname.InvalidatePlot(true);

and it must run on the UI dispatcher thread, ie

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



回答2:


Don't know if people still need this but I was having the same problems with itemsource not updating chart. 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....).

When i tried assigning already initialized collection to my itemsource, whole thing started working.

Hope this helps someone.




回答3:


I know this is an old question but maybe someone will use my answer after hours of double checking. I use MVVM. I'm updating the data with await Task.Run(()=> update()); and that wasn't rendering my plot in my UI. I was also initializing my PlotModel before setting it. Turns out, initializing the PlotModel in that update() method wasn't registering in my UI. I had to initialize it before I called that Task to run.

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;
}


来源:https://stackoverflow.com/questions/23542684/oxyplot-not-refreshing-when-using-data-binding-in-wpf

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!