08-18-2017 10:51 AM
When I am plotting some points on a graph, I use a few of the graph's events to modify the input, so after the data has been processed and the renderer has been run, I want to re-assign the the graph to the modified data. In the dataprocessed event, I am calling graph.Data[0] = someList; It then throws this error: An observable collection cannot be modified during a change event. Does anyone know how to get around this? Is there another event that I can be firing that is not a change event where I can change the collection and therefore refresh the graph?
Thanks,
Kelly
08-18-2017 11:41 AM
General caveat: For both of the options described below, every change to the Data
collection will result in a new event being raised, which will cause the "change data" operation to fire again. For the first option, this may result in sluggish performance as the application deals with continuous change events. For the second option, the application may crash due to a stack overflow (the example for the second option includes a simple flag to avoid this).
A third alternative would be to use a timer to perform the updates, independent of what assigns data to the graph. As long as the timer fires at a reasonable interval, the application should remain responsive, and the timer can be enabled or disabled as needed.
Getting back to the original question, I believe the best option would be to use the WPF dispatcher to queue the data assignment for later. It will be guaranteed to happen after the collection change has finished, and is safe to do from any event. (Note that DataProcessed
can fire in response to non-data changes, such as the graph being resized, so you may want to use an event on the Data
collection instead.)
graph.DataProcessed += OnGraphDataProcessed; ... private void OnGraphDataProcessed( object sender, DataProcessedEventArgs e ) { // Queue the change action (at low priority, so that the application stays responsive). Dispatcher.BeginInvoke( new Action( ChangeData ), DispatcherPriority.Background ); }
The other option would be to use the CollectionChanged
event on the Data
collection. This event happens after the collection change has gone through.
INotifyCollectionChanged notify = graph.Data; notify.CollectionChanged += OnDataCollectionChanged; ... // If we are not already in the process of changing the collection, modify and re-assign the data. private void OnDataCollectionChanged( object sender, NotifyCollectionChangedEventArgs e ) { if( changing ) return; ... changing = true; ChangeData( ); changing = false; }