OxyPlot ไม่รีเฟรชเมื่อใช้การเชื่อมโยงข้อมูลใน WPF

ฉันกำลังรับข้อมูลแบบอะซิงโครนัสและพยายามเติมข้อมูลพล็อตผ่าน LineSeries ยกเว้นว่าพล็อตไม่รีเฟรชเมื่อมีการอัปเดตคอลเลกชันที่ถูกผูกไว้ (ObservableCollection) หมายเหตุ: ฉันมีพฤติกรรม XAML ที่จะเรียก InvalidatePlot(true) เมื่อการเปลี่ยนแปลงคอลเลกชันที่ถูกผูกไว้

มีใครอธิบายได้บ้างว่าทำไมโครงเรื่องจึงไม่อัปเดตตามที่คาดไว้

WPF .Net 4.0 OxyPlot 2014.1.293.1

ฉันมีเทมเพลตข้อมูล XAML ต่อไปนี้ ตามที่คุณเห็น LineSeries ItemsSource ถูกผูกไว้กับคุณสมบัติ (PlotData) ใน 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>

ดังที่ฉันกล่าวว่าคำขอ 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 มีลักษณะดังนี้:

(ดูเหมือนว่าฉันไม่สามารถวางโค้ดได้อีกต่อไป ดังนั้นจึงเกิดข้อผิดพลาดในการบันทึก)


person AwkwardCoder    schedule 08.05.2014    source แหล่งที่มา
comment
RangeObservableCollectionคืออะไร? นอกจากนี้ มันจะสร้างความแตกต่างหรือไม่หากพร็อพเพอร์ตี้ของคุณเป็น ObservableCollection แทนที่จะเป็น IEnumerable<> ฉันรู้ว่าสมาชิกข้อมูลพื้นฐานคือ (สมมติว่า RangeObservableCollection มาจาก ObservableCollection) แต่ฉันไม่แน่ใจว่านั่นดีเพียงพอสำหรับระบบการเชื่อมโยงหรือไม่   -  person Tim    schedule 08.05.2014
comment
มันได้มาจาก ObservableCollection ฉันเปลี่ยนให้เป็น ObservableCollection แล้ว แต่ก็ยังไม่รีเฟรช   -  person AwkwardCoder    schedule 08.05.2014
comment
ฉันรู้ว่า BackgroundWorker รองรับการรายงานผลลัพธ์ _disposable มีฟังก์ชันดังกล่าวหรือไม่   -  person XAMlMAX    schedule 08.05.2014
comment
การอัปเดตออบเจ็กต์ OxyPlot ทั้งหมดเสร็จสิ้นบนเธรด UI   -  person AwkwardCoder    schedule 08.05.2014
comment
ขออภัยหากฉันหยาบคาย แต่คุณได้ดู ตัวอย่าง คุณควรอ่านโค้ดของคุณอีกครั้งและเปรียบเทียบสิ่งที่มีร่วมกันกับตัวอย่าง ฉันแน่ใจว่าคุณจะพบมันในไม่ช้า   -  person XAMlMAX    schedule 09.05.2014


คำตอบ (3)


OxyPlot ไม่อัปเดตโดยอัตโนมัติเมื่อคุณเพิ่มข้อมูล

คุณต้องเรียก plotname.InvalidatePlot(true);

และจะต้องทำงานบนเธรดตัวเลือกจ่ายงาน UI เช่น

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

ไม่รู้ว่าผู้คนยังต้องการสิ่งนี้อยู่หรือเปล่า แต่ฉันประสบปัญหาเดียวกันกับ itemsource ที่ไม่อัปเดตแผนภูมิ และไม่มีวิธีแก้ไขปัญหาใดที่มีอยู่ช่วยฉันได้

ในที่สุดฉันก็พบสาเหตุที่ทำให้ทุกอย่างไม่ทำงาน ฉันได้กำหนดคอลเลกชันของฉันให้กับ itemsource ก่อนที่จะเริ่มต้นใช้งานจริง (สังเกตได้ใหม่....)

เมื่อฉันพยายามกำหนดคอลเลกชันที่เริ่มต้นแล้วให้กับ itemsource ของฉัน ทุกอย่างก็เริ่มทำงาน

หวังว่านี่จะช่วยใครซักคน

person Ales    schedule 25.02.2015
comment
เช่นเดียวกับฉัน InvalidatePlot(true) ที่นี่และที่นั่น วางจำนวน ObservableCollection ไว้ข้างๆ กล่องข้อความ... มันอาจจะง่ายมาก เหมือนที่ Ales ต้องย้าย SampleValues = new ObservableCollection<Reading>(); ไว้เหนือ InitializeComponent(); เท่านั้น - person MarkusEgle; 25.01.2019

ฉันรู้ว่านี่เป็นคำถามเก่า แต่อาจมีบางคนใช้คำตอบของฉันหลังจากตรวจสอบซ้ำหลายชั่วโมงแล้ว ฉันใช้ MVVM ฉันกำลังอัปเดตข้อมูลโดย await Task.Run(()=> update()); และนั่นไม่ได้แสดงพล็อตของฉันใน UI ของฉัน ฉันยังเริ่มต้น PlotModel ของฉันก่อนที่จะตั้งค่า ปรากฎว่าการเริ่มต้น PlotModel ในเมธอด update() นั้นไม่ได้ลงทะเบียนใน UI ของฉัน ฉันต้องเริ่มต้นมันก่อนที่จะเรียกงานนั้นให้ทำงาน

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