Measurement Studio for .NET Languages

cancel
Showing results for 
Search instead for 
Did you mean: 

wpf graph - remove plot

When I use graph.Plots.Remove( plot ), plot changes its color instead of disappearing. How do I remove plot from graph properly?

0 Kudos
Message 1 of 12
(7,752 Views)

The only required member on the WPF graphs is Data (or DataSource). When a graph is provided with data, it will always diplay that data using the configured plots and axes, falling back to a default configuration if necessary.


When you call graph.Plots.Remove on the last plot in the graph, this will remove the renderer associated with the plot from the graph, but the data in the graph will be left unchanged. While processing this change, the graph will see that there is no plot specified and will fallback to the approriate renderer in the DefaultPlotRenderers or FallbackRenderers collections. If the fallback renderer is configured with the same type of renderer as that on the removed plot, but using a different brush, then the end result is the plot will change color.


If you want to remove data from the graph, you need to remove it from the Data collection, or from your DataSource. If you just want to hide a particular plot temporarily, then you can change the Visibility of the plot.

~ Paul H
Message 2 of 12
(7,744 Views)

ok, let's say I've got 20 plots which I want to remove:

 

foreach (var plot in PlotsHistory)
{
  graph.Data.RemoveAt(plot.Index); 
  graph.Plots.Remove(plot);
}

 

and this code fails when trying to remove second plot in the collection. I've tried to remove only from graph.Data, but it didn't help so much.

0 Kudos
Message 3 of 12
(7,727 Views)

I was able to reproduce this issue and confirm there is an error in how the graph is processing multiple removes.


To workaround this issue in the current Measurement Studio release, you can either 1) avoid removing the plots and data, or 2) perform the remove in two steps.


For option 1, instead of removing the data, simply set graph.Data[plot.Index] to null. This will remove the data for that plot from the graph, without changing the order of the plots in any other way.


For option 2, you would build up a collection of the final data and plot items you want in the graph, then clear the graph and add all the saved items. Here is a quick example using LINQ, based on your code snippet:


    var data = graph.Data.Where( (d, i) => PlotHistory.Any( p => p.Index == i ) ).ToArray( );
    var plots = graph.Plots.Except( PlotHistory ).ToArray( );
    graph.Data.Clear( );
    graph.Plots.Clear( );
    graph.Plots.AddRange( plots );
    graph.Data.AddRange( data );

~ Paul H
0 Kudos
Message 4 of 12
(7,719 Views)

I think it should be 

var data = graph.Data.Where( (d, i) => !PlotsHistory.Exists( p => p.Index == i ) ).ToArray( );

 

but anyway, it crashes at this line

graph.Data.AddRange( data );

 

both data and plots contain single item

0 Kudos
Message 5 of 12
(7,704 Views)

Yes, your snippet is correct (that’s what I get for retyping instead of using copy-and-paste :).


I have attached the project I used to reproduce the original issue. When I changed the PlotHistory condition to leave a single element, I did not experience a crash. Was this the same exception you saw before, or a new one? It would help us address your problem if you could edit the project to reproduce the crash, or provide the stack trace for the new error.

~ Paul H
0 Kudos
Message 6 of 12
(7,697 Views)

Hi, Paul!

 

I just looked at the exception again and it seems that problem is with cursor, not with plot removal itself. Note that I've got some cursors on the graph, but they are hidden.

 

at System.ThrowHelper.ThrowArgumentOutOfRangeException()
at System.Collections.Generic.List`1.get_Item(Int32 index)
at NationalInstruments.Controls.Primitives.NotifyingCollection`1.get_Item(Int32 index)
at System.Collections.ObjectModel.ReadOnlyCollection`1.get_Item(Int32 index)
at NationalInstruments.Controls.Internal.QueryableGraphHelper.a(IPlotObserver A_0, BufferCollection A_1, Int32 A_2)
at NationalInstruments.Controls.Internal.QueryableGraphHelper.FindNearestValue(IPlotObserver startingPlot, Point relativeStart, GraphQueryArgs args)
at NationalInstruments.Controls.Graph.FindNearestValueCore(IPlotObserver startingPlot, Point relativePosition, GraphQueryArgs args)
at NationalInstruments.Controls.Primitives.LayeredGraph.FindNearestValue(IPlot startingPlot, Point relativePosition, GraphQueryArgs args)
at NationalInstruments.Controls.Cursor.b(IList A_0)
at NationalInstruments.Controls.Cursor.d()
at NationalInstruments.Controls.Cursor.a(Object A_0, DataProcessedEventArgs A_1)
at System.EventHandler`1.Invoke(Object sender, TEventArgs e)
at NationalInstruments.Controls.Primitives.GraphBase.OnDataProcessed(DataProcessedEventArgs e)
at NationalInstruments.Controls.Graph.NationalInstruments.Controls.Internal.IDefaultDataProcessorTarget.ReceiveData(IDictionary`2 data)
at NationalInstruments.Controls.Internal.DefaultPipelineDataProcessor.a(ICollection`1 A_0)
at NationalInstruments.Controls.Internal.DefaultPipelineDataProcessor.ProcessDataCore(IDictionary`2 changedData)
at NationalInstruments.Controls.Primitives.DataProcessorBase.ProcessData(IDictionary`2 changedData)
at NationalInstruments.Controls.Primitives.GraphBase.a(IDictionary`2 A_0)
at NationalInstruments.Controls.Primitives.GraphBase.<>c__DisplayClassa.<OnDataCollectionChanging>b__8()
at System.Action.Invoke()
at NationalInstruments.Controls.Primitives.NotifyingCollection`1.ChangeItemsCore(Int32 index, Int32 removeCount, T[] newItems)
at NationalInstruments.Controls.Primitives.DataCollection.ChangeItemsCore(Int32 index, Int32 removeCount, Object[] newItems)
at NationalInstruments.Controls.Primitives.NotifyingCollection`1.ChangeItems(Int32 index, Int32 removeCount, T[] newItems)
at NationalInstruments.Controls.Primitives.NotifyingCollection`1.AddRange(IEnumerable`1 newItems)

0 Kudos
Message 7 of 12
(7,638 Views)

If you add one cursor to your sample, it will crash when deleting plots...

0 Kudos
Message 8 of 12
(7,636 Views)

I was able to reproduce the error using MStudio 2012 with the cursor. The exception is caused by a reset to the state of the graph when plots are removed.


Returning data does not restore the state of the graph, but you can workaround this by forcing the state to re-initialize. Before the call to graph.Data.AddRange( data ) in the RemovePlotData program, you can add the following line to avoid the exception:


    ...
    graph.Plots.Clear( );
    graph.Data.AddRange( Enumerable.Repeat( new int[0], data.Length ) );
    graph.Data.AddRange( data );
    ...


When the data type changes from double to int, this forces the graph to correct its state.

~ Paul H
0 Kudos
Message 9 of 12
(7,626 Views)

but in this way I add data twice, which I've checked, and so additional plot will appear...

0 Kudos
Message 10 of 12
(7,622 Views)