I want to drow so many graphs with OxyPlot Library.
And I'm testing now that I can add how many graphs with dynamic (but I'll not add graphs over 10000 graphs because it's max graphs in real application).
However when I'll add over 200 graphs, the Oxyplot throw exception.
Exception message is "This PlotModel is already in use by some other PlotView control.".
There are all of my code. (In code, I add graph with dynamic and I add values to the all graphs each 5 second in other thread.)
//Xaml -- MainView
<Window x:Class="OxyplotStressTest.MainWindow"
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:oxy="clr-namespace:OxyPlot.Wpf;assembly=OxyPlot.Wpf"
xmlns:local="clr-namespace:OxyplotStressTest"
mc:Ignorable="d"
Title="MainWindow" Height="550" Width="725">
<Grid>
<Button Content="Add 100" HorizontalAlignment="Left" Height="32" Margin="20,23,0,0" VerticalAlignment="Top" Width="65" Click="Button_Click100"/>
<Button Content="Add 50" HorizontalAlignment="Left" Height="32" Margin="102,23,0,0" VerticalAlignment="Top" Width="65" Click="Button_Click50"/>
<Button Content="Add 10" HorizontalAlignment="Left" Height="32" Margin="189,23,0,0" VerticalAlignment="Top" Width="65" Click="Button_Click10"/>
<Button Content="Add 1" HorizontalAlignment="Left" Height="32" Margin="274,23,0,0" VerticalAlignment="Top" Width="65" Click="Button_Click1"/>
<Grid Margin="20,65,19,10">
<ScrollViewer>
<ItemsControl ItemsSource="{Binding List}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<Label Content="{Binding Tag}"/>
<oxy:PlotView HorizontalAlignment="Left" Height="130" Margin="20,23,0,0" VerticalAlignment="Top" Width="600"
Model="{Binding Chart}" IsMouseWheelEnabled="False" IsManipulationEnabled="False" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
</Grid>
//C# -- MainWindow.cs
public partial class MainWindow : Window
{
private MainWindowViewModel mMainWindowViewModel = null;
public MainWindow()
{
InitializeComponent();
MainWindowViewModel mainWindowViewModel = new MainWindowViewModel();
this.DataContext = mainWindowViewModel;
mMainWindowViewModel = mainWindowViewModel;
Thread thread = new Thread(new ParameterizedThreadStart(reloadGraph));
thread.Start();
}
private void Button_Click100(object sender, RoutedEventArgs e)
{
AddGraph addGraph = new AddGraph(mMainWindowViewModel);
addGraph.addGraph(100);
}
private void Button_Click50(object sender, RoutedEventArgs e)
{
AddGraph addGraph = new AddGraph(mMainWindowViewModel);
addGraph.addGraph(50);
}
private void Button_Click10(object sender, RoutedEventArgs e)
{
AddGraph addGraph = new AddGraph(mMainWindowViewModel);
addGraph.addGraph(10);
}
private void Button_Click1(object sender, RoutedEventArgs e)
{
AddGraph addGraph = new AddGraph(mMainWindowViewModel);
addGraph.addGraph(1);
}
private void reloadGraph(object param)
{
while (true)
{
Thread.Sleep(5000);
if (mMainWindowViewModel.List.Count > 0)
{
AddGraph addGraph = new AddGraph(mMainWindowViewModel);
addGraph.reloadGraph();
}
Console.WriteLine(Environment.WorkingSet.ToString());
}
}
}
//C# -- MainViewModel
public MainWindowViewModel()
{
listVal = new ObservableCollection<Items>();
BindingOperations.EnableCollectionSynchronization(this.listVal, new object());
}
private ObservableCollection<Items> listVal = new ObservableCollection<Items>();
public ObservableCollection<Items> List
{
get
{
return listVal;
}
set
{
listVal = value;
NotifyPropertyChanged("List");
}
}
public class Items
{
public string Tag { get; set; }
private PlotModel chartVal = new PlotModel();
public PlotModel Chart
{
get
{
return chartVal;
}
set
{
chartVal = value;
}
}
}
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
//C# -- Model Class
class AddGraph
{
private MainWindowViewModel mMainWindowViewModel = null;
public AddGraph(MainWindowViewModel pMainWindowViewModel)
{
mMainWindowViewModel = pMainWindowViewModel;
}
public void addGraph(int pCount)
{
try
{
for (int i = 0; i < pCount; i++)
{
Random random = new Random();
long data = random.Next(100);
ColumnSeries column = new ColumnSeries();
column.FillColor = OxyColors.SkyBlue;
column.Items.Add(new ColumnItem() { Value = data });
data *= random.Next(50);
column.Items.Add(new ColumnItem() { Value = data });
Items items = new Items();
items.Tag = mMainWindowViewModel.List.Count.ToString();
items.Chart.Series.Add(column);
items.Chart.InvalidatePlot(true);
mMainWindowViewModel.List.Add(items);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
public void reloadGraph()
{
try
{
List<Items> newList = new List<Items>();
foreach (Items listItem in mMainWindowViewModel.List)
{
string tag = listItem.Tag;
PlotModel plotModel = listItem.Chart;
ColumnSeries oldGraph = (ColumnSeries)plotModel.Series[0];
ColumnSeries newGraph = new ColumnSeries();
newGraph.FillColor = OxyColors.SkyBlue;
for (int i = 0; i < oldGraph.Items.Count; i++)
{
if (oldGraph.Items.Count == 30 && i == 0)
{
continue;
}
newGraph.Items.Add(new ColumnItem() { Value = oldGraph.Items[i].Value });
}
Random random = new Random();
long val = random.Next(500);
val *= random.Next(50);
newGraph.Items.Add(new ColumnItem() { Value = val });
Items items = new Items();
items.Tag = tag;
items.Chart.Series.Add(newGraph);
items.Chart.InvalidatePlot(true);
newList.Add(items);
}
#region //there are my solution and it shows good performance
int index = 0;
foreach (var addItem in newList)
{
mMainWindowViewModel.List[index] = addItem;
index++;
}
#endregion
#region //there are my first code and it has problem
mMainWindowViewModel.List.Clear();
foreach (var addItem in newList)
{
mMainWindowViewModel.List.Add(addItem);
}
#endregion
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
Maybe my code is bad, but I don't know where is the bad code because it dosen't stop on BreakPoint.
If you give me a advice, I'm so glad.