数据更改时如何刷新氧图
Posted
技术标签:
【中文标题】数据更改时如何刷新氧图【英文标题】:How to refresh oxyplot plot when data changes 【发布时间】:2014-01-22 12:58:40 【问题描述】:Oxyplot 绘制 13 个点,这些点来自 6 个用户输入文本框。文本框中的值保存在 MainWindow.xaml.cs 类的公共变量中。当用户在文本框中按下回车键时,变量会更新。如何让刷新按钮刷新图表。
private void RefreshButton_Click(object sender, RoutedEventArgs e)
//Refresh The Graph
我认为这将使用
PlotModel.RefreshPlot()
方法,但由于 Oxyplot 的文档很差,我不确定如何实现它。
【问题讨论】:
抱歉来晚了两年,但是这里没有给出最好的方法。要正确执行此操作,请使用 oxyplot.wpf,不要使用 PlotModel - 使用 Plot,并将您的数据绑定到 ItemsSourceProperty - 无需调用 Invalidate!它随着数据的实时更新而更新。 哇。我不敢相信这仍然是活跃的。这个项目很久以前了。 @AndrewBenjamin 在当前版本(2022)中似乎没有更多的Plot
@Jkallus 它仍然处于活动状态,因为您没有接受任何答案。
【参考方案1】:
我刚刚通过 NuGet 更新到新版本的 OxyPlot。我正在使用 OxyPlot.Wpf v20014.1.277.1,我认为您现在需要在 PlotModel
上调用 InvalidatePlot(bool updateData)
而不是 RefreshPlot(不再可用)。我在示例代码中对此进行了测试,它按预期工作。
如果要刷新绘图和更新数据集合,则需要将true
传递给调用:
PlotModel.InvalidatePlot(true)
【讨论】:
有点题外话了,但是您认为将 MVVM 用于一个使用 Oxy 绘图的非常小的项目有意义吗?还是Plot.Model = ...
和InvalidatePlot
足够好?我知道这是一个棘手的问题,但你的第一个想法是什么?
不需要将true
作为参数传递,它是参数的默认值。另外,我确认 RefreshPlot
在新版本中不再可用。【参考方案2】:
在 XAML 中将 x:Name
给 OxyPlot 实例:
<oxy:Plot x:Name="Plot1"/>
在按钮单击处理程序上,刷新如下:
private void RefreshButton_Click(object sender, RoutedEventArgs e)
Plot1.RefreshPlot(true);
【讨论】:
已弃用,不再可用【参考方案3】:我发现获得“某种”自动更新的最简洁方法是对 LineSeries 的 ItemsSource 集合上的 CollectionChanged 做出反应。
在 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);
【讨论】:
很好的答案。这就是绑定的方式。在我的中,我将 ViewModel 设置为 BindableObject 并调用 OnPropertyChanged() 而不是 RaisePropertyChanged()。 @DrCJones 引发PropertyChanged
事件的方法取决于您使用的 MVVM 库。使用 MvvmLight,ViewModels 通常继承自 ViewModelBase
,它具有 RaisePropertyChanged
方法。其他库可能不同。
好点@heltonbiker!我没有提到我在 Xamarin 项目中。【参考方案4】:
在当前的 OxyPlot.Wpf (1.0.0-unstable1983) 中,您有两种选择:
-
将 XAML 中的
Series.ItemsSource
属性绑定到视图模型中的集合,并在需要更新时交换整个集合。这还允许使用更大的数据集进行并发异步更新。
将int
类型的Plot.InvalidateFlag
属性绑定到您的视图模型,并在您需要更新时递增。不过,我还没有测试过这种方法。
以下代码说明了这两个选项(选择一个)。 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++;
【讨论】:
当前版本(2.1.0)中没有Plot
,对吧?还是我使用了错误的 xmlns?【参考方案5】:
在遇到同样的问题后,似乎唯一可行的解决方案(至少在我看来)如下:
PlotView.InvalidatePlot(true)
这样做,在更新一个或多个Series
后,请刷新您的PlotView
。
刷新率取决于您的系列的更新频率或更新率。
这是一个代码 sn-p(在 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's 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's 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
也会在发生触摸、捏合缩放或任何类型的 UI 相关事件等事件时更新。
我希望我能帮上忙。我为此困扰了很长时间。
【讨论】:
【参考方案6】:存在三种选择如何刷新情节(来自OxyPlot documentation):
更改PlotView
控件的Model
属性
在PlotView
控件上调用Invalidate
拨打Invalidate
PlotModel
【讨论】:
【参考方案7】:又过了两年……这个解决方案对我有用,因为我没有 oxyplot 模型,而且我错过了上面的一些命名函数。
后面的代码:
public partial class LineChart : UserControl
public LineChart()
InitializeComponent();
DataContext = this;
myChart.Title = "hier könnte Ihr Text stehen!";
this.Points = new List<DataPoint>();
randomPoints();
public IList<DataPoint> Points get; private set;
public void randomPoints()
Random rd = new Random();
String myText = "";
int anz = rd.Next(30, 60);
for (int i = 0; i < anz; i++)
myText += i + "," + rd.Next(0, 99) + ";";
myText = myText.Substring(0, myText.Length - 1);
String[] splitText = myText.Split(';');
for (int i = 0; i < splitText.Length; i++)
String[] tmp = splitText[i].Split(',');
Points.Add(new DataPoint(Double.Parse(tmp[0].Trim()), Double.Parse(tmp[1].Trim())));
while (Points.Count > anz)
Points.RemoveAt(0);
myChart.InvalidatePlot(true);
要更新您的数据,不要交换整个 IList,而是向其中添加一些新的 DataPoints 并删除位置 0 处的旧数据点。
XAML:
<UserControl x:Class="UxHMI.LineChart"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:UxHMI"
xmlns:oxy="http://oxyplot.org/wpf"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid x:Name="Container" Background="White">
<oxy:Plot x:Name="myChart" Title="Binding Title" FontFamily="Bosch Sans Medium" Foreground="#FF0C6596" FontSize="19" Canvas.Left="298" Canvas.Top="32" Background="AliceBlue" Margin="0,0,10,0">
<oxy:Plot.Series>
<oxy:LineSeries x:Name="ls" Background="White" ItemsSource="Binding Points" LineStyle="Solid" Color="ForestGreen" MarkerType="None" MarkerSize="5" MarkerFill="Black">
</oxy:LineSeries>
</oxy:Plot.Series>
</oxy:Plot>
<Button x:Name="button" Content="Random" HorizontalAlignment="Left" Margin="0,278,0,0" VerticalAlignment="Top" Width="75" Click="button_Click"/>
</Grid>
重要的是 x:Name="myChart" 和 ItemsSource="Binding Points"
我希望这对那里的人有用
【讨论】:
以上是关于数据更改时如何刷新氧图的主要内容,如果未能解决你的问题,请参考以下文章
当另一个片段中的数据发生更改时,如何刷新一个片段中的 RecyclerView
当sqlite android片段中的数据更改或删除时如何刷新recyclerview?