2

バインドされたコレクション (ObservableCollection) が更新されたときにプロットが更新されないことを除いて、非同期でデータを取得し、LineSeries を介してプロットを作成しようとしています。注: バインドされたコレクションが変更されたときに InvalidatePlot(true) を呼び出す XAML 動作があります。

プロットが期待どおりに更新されない理由を誰か説明できますか?

WPF .Net 4.0 OxyPlot 2014.1.293.1

LineSeries ItemsSource が ViewModel のプロパティ (PlotData) にバインドされていることがわかるように、次の XAML データ テンプレートがあります。

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

先ほど述べたように、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; }
    }
}

XAML の動作は次のようになります。

(もうコードを貼り付けられないようです。SOは保存時にエラーをスローし続けます)

4

3 に答える 3

6

OxyPlot は、データを追加しても自動的に更新されません。

plotname.InvalidatePlot(true); を呼び出す必要があります。

UI ディスパッチャ スレッドで実行する必要があります。つまり、

Dispatcher.InvokeAsync(() => 
{
    plotname.InvalidatePlot(true);
}
于 2014-10-12T12:14:25.613 に答える
2

人々がまだこれを必要としているかどうかはわかりませんが、アイテムソースがチャートを更新しないという同じ問題がありました。そして、既存のソリューションはどれも私を助けませんでした。

さて、私はついにすべてがうまくいかなかった理由を見つけました。コレクションを実際に初期化する前に itemsource に割り当てました (新しい Observable....)。

既に初期化されたコレクションをアイテムソースに割り当てようとすると、すべてが機能し始めました。

これが誰かに役立つことを願っています。

于 2015-02-25T11:39:12.643 に答える