OxyPlot 图形不更新
OxyPlot graphic doesn't update
我正在使用 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++;
}
}
我还需要做其他事情吗?
有
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
.
的情况下更新它的点
请注意,需要使用 UI 线程来更改 ObservableCollection
中的项目,如 this question 中所述。由于您正在使用其他线程来添加调用 UI like
的值
Application.Current.Dispatcher.BeginInvoke(() =>
{
BestFitness.Add(new DataPoint(count, args.BestFitness));
});
为必填项。
我创建了这个小示例来展示如何在运行时更新图形。希望对您有所帮助!
视图模型:
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>
我正在使用 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++;
}
}
我还需要做其他事情吗?
有
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
.
请注意,需要使用 UI 线程来更改 ObservableCollection
中的项目,如 this question 中所述。由于您正在使用其他线程来添加调用 UI like
Application.Current.Dispatcher.BeginInvoke(() =>
{
BestFitness.Add(new DataPoint(count, args.BestFitness));
});
为必填项。
我创建了这个小示例来展示如何在运行时更新图形。希望对您有所帮助!
视图模型:
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>