我正在使用C#,.NET Framework 4.7开发WPF应用程序。和Oxyplot 1.0。
我试图在运行时更新图形,但它没有做任何事情。
我尝试使用ObsevableCollection
和InvalidateFlag
,但没有成功。
这是XAML:
<oxy:Plot Title="{Binding Title}" InvalidateFlag="{Binding InvalidateFlag}">
<oxy:Plot.Series>
<oxy:LineSeries ItemsSource="{Binding BestFitness}"/>
<oxy:LineSeries ItemsSource="{Binding WorstFitness}"/>
<oxy:LineSeries ItemsSource="{Binding AverageFitness}"/>
</oxy:Plot.Series>
</oxy:Plot>
这是视图模型:
public class MainViewModel : ObservableObject
{
private int count;
private int _invalidateFlag;
public string Title { get; set; }
public int InvalidateFlag
{
get { return _invalidateFlag; }
set
{
_invalidateFlag = value;
RaisePropertyChangedEvent("InvalidateFlag");
}
}
public ObservableCollection<DataPoint> BestFitness { get; set; }
public ObservableCollection<DataPoint> WorstFitness { get; set; }
public ObservableCollection<DataPoint> AverageFitness { get; set; }
public ICommand StartCommand
{
get { return new DelegateCommand(Start); }
}
public ICommand RefereshCommand
{
get { return new DelegateCommand(Refresh); }
}
public MainViewModel()
{
this.Title = "Example 2";
this.BestFitness = new ObservableCollection<DataPoint>
{
new DataPoint(0, 4),
new DataPoint(10, 13),
new DataPoint(20, 15),
new DataPoint(30, 16),
new DataPoint(40, 12),
new DataPoint(50, 12)
};
}
private void Start()
{
Random rnd = new Random((int)DateTime.Now.Ticks);
Program program = new Program(rnd);
program.Algorithm.EvolutionEnded += Algorithm_EvolutionEnded;
count = 0;
this.BestFitness = new ObservableCollection<DataPoint>();
this.WorstFitness = new ObservableCollection<DataPoint>();
this.AverageFitness = new ObservableCollection<DataPoint>();
Task.Run(() => program.Run(null));
}
private void Refresh()
{
this.BestFitness.Clear();
}
private void Algorithm_EvolutionEnded(object sender, EventArgs e)
{
EvolutionEndedEventArgs args = (EvolutionEndedEventArgs)e;
BestFitness.Add(new DataPoint(count, args.BestFitness));
WorstFitness.Add(new DataPoint(count, args.WorstFitness));
AverageFitness.Add(new DataPoint(count, args.AverageFitness));
InvalidateFlag++;
}
}
我还需要做其他事吗?
答案 0 :(得分:1)
使用
this.BestFitness = new ObservableCollection<DataPoint>();
...
你正在取代情节的完整ItemsSource
。由于之后通过调用RaisePropertyChangedEvent
没有关于视图的通知,绑定的绘图将无法识别更改,并且绘图将不会更新它的点。
有两种可能的解决方案:
<强> 1。替换集合后,通过调用RaisePropertyChangedEvent
来使用INotifyPropertychanged 。因此
public ObservableCollection<DataPoint> BestFitness { get; set; }
应该扩展到
private ObservableCollection<DataPoint> _BestFitness;
public ObservableCollection<DataPoint> BestFintess
{
get
{
return _BestFitness;
}
private set
{
_BestFitness = value;
RaisePropertyChangedEvent(nameof(BestFintess));
}
}
<强> 2。不要替换整个ObservableCollection。只需清除现有的集合并再次使用它们。这意味着使用
this.BestFitniss.Clear();
而不是
this.BestFitness = new ObservableCollection<DataPoint>();
两个解决方案都会通知视图有关更改和图表,而不会使用InvalidateFlag
来更新点数。
请注意,如this question中所述,需要使用UI线程更改ObservableCollection
的项目。由于您正在使用其他线程来添加调用UI的值,如
Application.Current.Dispatcher.BeginInvoke(() =>
{
BestFitness.Add(new DataPoint(count, args.BestFitness));
});
是必需的。
答案 1 :(得分:0)
我创建了这个小例子来展示如何在运行时更新图形。我希望它有所帮助!
视图模型:
using System;
using System.Timers;
using OxyPlot;
using OxyPlot.Series;
namespace WpfApp1
{
public class MainViewModel
{
private LineSeries lineSeries;
private int count;
public MainViewModel()
{
this.MyModel = new PlotModel { Title = "Example 1" };
//this.MyModel.Series.Add(new FunctionSeries(Math.Cos, 0, 10, 0.1, "cos(x)"));
//this.MyModel.Series.Add(new FunctionSeries(Math.Sin, 0, 10, 0.1, "sin(x)"));
lineSeries = new LineSeries();
lineSeries.LineStyle = LineStyle.Solid;
lineSeries.StrokeThickness = 2.0;
lineSeries.Color = OxyColor.FromRgb(0, 0, 0);
this.MyModel.Series.Add(lineSeries);
Timer timer = new Timer(1000);
timer.Elapsed += Timer_Elapsed;
timer.Start();
count = 0;
}
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
lineSeries.Points.Add(new DataPoint(count, Math.Pow(count, 2)));
this.MyModel.InvalidatePlot(true);
count++;
}
public PlotModel MyModel { get; private set; }
}
}
XAML:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
xmlns:oxy="http://oxyplot.org/wpf" x:Class="WpfApp1.MainWindow"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Grid>
<oxy:PlotView Model="{Binding MyModel}" />
</Grid>
</Window>