OxyPlot tidak menyegarkan saat menggunakan pengikatan data di WPF

Saya secara tidak sinkron mendapatkan data dan mencoba mengisi plot melalui LineSeries, kecuali plot tersebut tidak disegarkan ketika koleksi terikat (ObservableCollection) diperbarui. Catatan: Saya memiliki perilaku XAML untuk memanggil InvalidatePlot(true) ketika koleksi terikat berubah.

Adakah yang bisa menjelaskan mengapa plotnya tidak diperbarui seperti yang diharapkan?

WPF .Net 4.0 OxyPlot 2014.1.293.1

Saya memiliki templat data XAML berikut, seperti yang Anda lihat LineSeries ItemsSource terikat ke properti (PlotData) di 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>

Seperti yang saya katakan, ViewModel meminta dan mengisi koleksi terikat secara asinkron (populasi sebenarnya dari koleksi terikat terjadi di thread 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; }
    }
}

Dan perilaku XAML terlihat seperti ini:

(Sepertinya saya tidak bisa menempelkan kode lagi, SO terus membuat kesalahan saat menyimpan)


person AwkwardCoder    schedule 08.05.2014    source sumber
comment
Apa itu RangeObservableCollection? Selain itu, apakah ada bedanya jika properti Anda sebenarnya adalah ObservableCollection dan bukan IEnumerable<> ? Saya tahu anggota data yang mendasarinya adalah (dengan asumsi RangeObservableCollection berasal dari ObservableCollection) tapi saya tidak yakin apakah itu cukup baik untuk sistem pengikatan.   -  person Tim    schedule 08.05.2014
comment
itu berasal dari ObservableCollection, saya mengubahnya menjadi ObservableCollection dan masih tidak menyegarkan   -  person AwkwardCoder    schedule 08.05.2014
comment
Saya tahu bahwa BackgroundWorker Mendukung Pelaporan hasil, apakah _disposable memiliki fungsi seperti itu?   -  person XAMlMAX    schedule 08.05.2014
comment
semua pembaruan objek OxyPlot dilakukan di thread UI   -  person AwkwardCoder    schedule 08.05.2014
comment
Maafkan saya jika saya kasar tetapi pernahkah Anda melihat contoh. Anda harus memeriksa kode Anda lagi dan membandingkan hal-hal bersama dengan contoh. Saya yakin Anda akan segera menemukannya.   -  person XAMlMAX    schedule 09.05.2014


Jawaban (3)


OxyPlot tidak diperbarui secara otomatis saat Anda menambahkan data.

Anda harus memanggil plotname.InvalidatePlot(true);

dan itu harus berjalan di thread operator UI, yaitu

Dispatcher.InvokeAsync(() => 
{
    plotname.InvalidatePlot(true);
}
person Spiked3    schedule 12.10.2014

Tidak tahu apakah orang masih membutuhkan ini tetapi saya mengalami masalah yang sama dengan itemsource yang tidak memperbarui grafik. Dan tidak ada solusi yang membantu saya.

Akhirnya saya menemukan alasan mengapa semuanya tidak berhasil. Saya telah menugaskan koleksi saya ke itemsource sebelum saya benar-benar menginisialisasinya (Dapat Diamati baru....).

Ketika saya mencoba menugaskan koleksi yang sudah diinisialisasi ke sumber item saya, semuanya mulai berfungsi.

Semoga ini bisa membantu seseorang.

person Ales    schedule 25.02.2015
comment
Sama bagiku. InvalidatePlot(true) di sana-sini, letakkan hitungan ObservableCollection di samping dalam TextBox... Ini bisa sangat mudah, seperti Ales hanya perlu memindahkan SampleValues = new ObservableCollection<Reading>(); ke atas InitializeComponent(); - person MarkusEgle; 25.01.2019

Saya tahu ini adalah pertanyaan lama tetapi mungkin seseorang akan menggunakan jawaban saya setelah berjam-jam memeriksa ulang. Saya menggunakan MVVM. Saya memperbarui data dengan menunggu Task.Run(()=> update()); dan itu tidak menampilkan plot saya di UI saya. Saya juga menginisialisasi PlotModel saya sebelum mengaturnya. Ternyata, menginisialisasi PlotModel dalam metode update() itu tidak terdaftar di UI saya. Saya harus menginisialisasinya sebelum saya memanggil Tugas itu untuk dijalankan.

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;
}
person MegMeg48    schedule 26.10.2017