Как обновить график оксиплотов при изменении данных
![GUI for the program]()
Графики Oxyplot 13 точек, которые получены из 6 текстовых полей ввода пользователя. Значения в текстовых полях хранятся в общедоступных переменных в классе MainWindow.xaml.cs. Переменные обновляются, когда пользователь нажимает кнопку ввода в текстовое поле. Как сделать кнопку обновления обновить график.
private void RefreshButton_Click(object sender, RoutedEventArgs e)
{
//Refresh The Graph
}
Я думаю, что это будет сделано с помощью
PlotModel.RefreshPlot()
но я не уверен, как его реализовать из-за плохой документации Oxyplot.
Ответы
Ответ 1
Я только что обновил новую версию OxyPlot через NuGet. Я использую OxyPlot.Wpf v20014.1.277.1, и я думаю, теперь вам нужно вызвать InvalidatePlot(bool updateData)
в PlotModel
вместо RefreshPlot (который больше не доступен). Я тестировал это в своем примере кода, и он работал, как ожидалось.
Если вы хотите обновить график и обновить коллекции данных, вам необходимо передать true
на вызов:
PlotModel.InvalidatePlot(true)
Ответ 2
Дайте x:Name
экземпляру OxyPlot в XAML:
<oxy:Plot x:Name="Plot1"/>
и в обработчике щелчка на кнопке, выполните следующие действия:
private void RefreshButton_Click(object sender, RoutedEventArgs e)
{
Plot1.RefreshPlot(true);
}
Ответ 3
После того же вопроса с той же проблемой, казалось бы, единственное рабочее решение (по крайней мере, с моей точки зрения):
PlotView.InvalidatePlot(true)
Сделав это, после обновления одного или нескольких Series
обновите свой PlotView
.
Частота обновления зависит от того, как часто, или с какой скоростью обновляются ваши обновления.
Вот фрагмент кода (на Xamarin Android, но он должен работать в любом случае):
PlotView resultsChart = FindViewById<PlotView>(Resource.Id.resultsChart);
PlotModel plotModel = new PlotModel
{
// set here main properties such as the legend, the title, etc. example :
Title = "My Awesome Real-Time Updated Chart",
TitleHorizontalAlignment = TitleHorizontalAlignment.CenteredWithinPlotArea,
LegendTitle = "I am a Legend",
LegendOrientation = LegendOrientation.Horizontal,
LegendPlacement = LegendPlacement.Inside,
LegendPosition = LegendPosition.TopRight
// there are many other properties you can set here
}
// now let define X and Y axis for the plot model
LinearAxis xAxis = new LinearAxis();
xAxis.Position = AxisPosition.Bottom;
xAxis.Title = "Time (hours)";
LinearAxis yAxis = new LinearAxis();
yAxis.Position = AxisPosition.Left;
yAxis.Title = "Values";
plotModel.Axes.Add(xAxis);
plotModel.Axes.Add(yAxis);
// Finally let define a LineSerie
LineSeries lineSerie = new LineSeries
{
StrokeThickness = 2,
CanTrackerInterpolatePoints = false,
Title = "Value",
Smooth = false
};
plotModel.Series.Add(lineSerie);
resultsChart.Model = plotModel;
Теперь, когда вам нужно добавить DataPoints
в LineSerie
и автоматически обновить PlotView
, выполните следующие действия:
resultsChart.InvalidatePlot(true);
Это автоматически обновит ваш PlotView
.
В боковом примечании PlotView
также будет обновляться, когда произойдет событие, такое как касание, щепотка для увеличения или любые связанные с пользовательским интерфейсом события.
Я надеюсь, что смогу помочь. У меня были проблемы с этим в течение очень долгого времени.
Ответ 4
В текущем OxyPlot.Wpf(1.0.0-unstable1983) у вас есть две возможности:
- Привязать свойство
Series.ItemsSource
из XAML к коллекции в вашей модели viewmodel и обмениваться всей коллекцией, когда вам нужно обновление. Это также позволяет одновременные обновления асинхронизации с большими наборами данных.
- Привязать свойство
Plot.InvalidateFlag
типа int
к вашей модели просмотра и приращению всякий раз, когда вам нужно обновление. Однако я не тестировал этот подход.
Следующий код иллюстрирует обе опции (выберите один). XAML:
<oxy:Plot InvalidateFlag="{Binding InvalidateFlag}">
<oxy:Plot.Series>
<oxy:LineSeries ItemsSource="{Binding DataSeries}" />
</oxy:Plot.Series>
</oxy:Plot>
Обновления в ViewModel:
private async Task UpdateAsync()
{
// TODO do some heavy computation here
List<DataPoint> data = await ...
// option 1: Trigger INotifyPropertyChanged on the ItemsSource.
// Concurrent access is ok here.
this.DataSeries = data; // switch data sets
// option 2: Update the data in place and trigger via flag
// Only one update at a time.
this.DataSeries.Clear();
data.ForEach(this.DataSeries.Add);
this.InvalidateFlag++;
}
Ответ 5
Самый чистый способ, которым я нашел автоматическое обновление "своего рода", реагирует на CollectionChanged в коллекции, которая является элементом ItemsSeries LineSeries.
В ViewModel:
ObservableCollection<DataPoint> Data { get; set; }
= new ObservableCollection<DataPoint>();
public PlotModel PlotModel
{
get { return _plot_model; }
set
{
_plot_model = value;
RaisePropertyChanged(() => PlotModel);
}
}
PlotModel _plot_model;
// Inside constructor:
Data.CollectionChanged += (a, b) => PlotModel.InvalidatePlot(true);
Ответ 6
Существует три альтернативы: как обновить график (из Документация OxyPlot):
- Измените свойство
Model
элемента управления PlotView
- Вызов
Invalidate
в элементе управления PlotView
- Вызовите
Invalidate
на PlotModel