From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

Measurement Studio for .NET Languages

cancel
Showing results for 
Search instead for 
Did you mean: 

An observable collection cannot be modified during a change event

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

0 Kudos
Message 1 of 2
(4,980 Views)

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;
}

 

~ Paul H
Message 2 of 2
(4,964 Views)