Why is my ObservableCollection collection changed event only firing once?

Forrest Crawford 80 Reputation points
2023-03-25T18:44:24.7833333+00:00

So, I've got a static collection called Globals.POINTS and I've added a collection changed event to it so that it updates a collection called MapPageBaseClassList whenever a point is added to the static collection. It works initially and the event is fired on the first point added to the global collection but the second point added does not fire the event. It only begins working again if I back out of the page but I cannot understand why this would happen. I am new to this.

Collection changed:

Globals.POINTS.CollectionChanged += POINTS_CollectionChanged;
private void POINTS_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == NotifyCollectionChangedAction.Add)
            {
                var newPointsList = e.NewItems;
                foreach (var item in newPointsList)
                {
                    PointClass point = (PointClass)item;
                    PointControl pointControl = new PointControl(
                        point, Globals.EXTENTS, Globals.MapPageCanvasSize.X, Globals.MapPageCanvasSize.Y, 1, point.MapPageCanvasCenter.X, point.MapPageCanvasCenter.Y);
                    pointControl.ScalePoint(currentPointScale);
                    pointControl.PropertyChanged += CanvasPropertyChanged;
                    Canvas.SetLeft(pointControl, pointControl.Left);
                    Canvas.SetTop(pointControl, pointControl.Top);
                    Globals.PointControlList.Add(pointControl);
                    Globals.MapPageBaseClassList.Insert(0, pointControl);
                    
                    MapPageBaseClassList = Globals.MapPageBaseClassList;
                }
            }
            if (e.Action == NotifyCollectionChangedAction.Remove)
            {
                var deletedPointsList = e.OldItems;
                foreach (var item in deletedPointsList)
                {
                    PointClass point = (PointClass)item;
                    var pointControl = MapPageBaseClassList.OfType<PointControl>().FirstOrDefault(x => x.PointName == point.Name);
                    Globals.PointControlList.Remove(pointControl);
                    Globals.MapPageBaseClassList.Remove(pointControl);
                    MapPageBaseClassList = Globals.MapPageBaseClassList;
                }
            }
            if (e.Action == NotifyCollectionChangedAction.Reset)
            {
                Globals.PointControlList.Clear();
                Globals.MapPageBaseClassList.Clear();
                MapPageBaseClassList = Globals.MapPageBaseClassList;
            }
        }

Here's where I add to the global collection:

 foreach (var point in highlightedPoints)
            {
                CanvasLayer canvasLayer;

                if (LayerCBox.SelectedIndex == 0)
                {
                    canvasLayer = GetNewCanvasLayer();
                }
                else
                {
                    canvasLayer = Globals.LAYER_LIST.FirstOrDefault(x => x.Name == LayerCBox.Text);
                }

                var pointClass = ValidatePointInfo(TextBox1.Text, TextBox2.Text, TextBox3.Text, TextBox4.Text, TextBox5.Text, canvasLayer);
                if (pointClass is null)
                {
                    return;
                }
                else
                {
                    TextBox1.Background = Brushes.White;
                    TextBox2.Background = Brushes.White;
                    TextBox3.Background = Brushes.White;
                    TextBox4.Background = Brushes.White;
                }

                point.Color = "Transparent";

                Globals.POINTS.Add(pointClass);
                Globals.SortPoints();
                Globals.SaveGlobals();   
            }
            highlightedPoints.Clear();
        }

Here's where I've defined the global variable, if that is of any help:

public static ObservableCollection<PointClass> POINTS
        {
            get { return points; }
            set
            {
                points = value;
                OnStaticPropertyChanged(nameof(POINTS));
            }
        }

I've confirmed that the point is added to the list but the event isn't triggered on the second add for some reason and I cannot begin to understand why.

Developer technologies | Windows Presentation Foundation
Developer technologies | C#
{count} votes

2 answers

Sort by: Most helpful
  1. Erkan Sahin 840 Reputation points
    2023-03-25T18:50:30.9566667+00:00

    It seems like the issue might be related to the fact that you are assigning the MapPageBaseClassList to Globals.MapPageBaseClassList within the foreach loop that iterates through the new items added to the POINTS collection.

    Instead of assigning MapPageBaseClassList to Globals.MapPageBaseClassList within the loop, you could simply set it once outside of the loop, after all the items have been added to Globals.MapPageBaseClassList. Like this:

    foreach (var item in newPointsList)
    {
        // ...
    }
    Globals.MapPageBaseClassList = MapPageBaseClassList.ToList();
    Additionally, it might be better to create a new instance of MapPageBaseClassList rather than updating the same instance, which could cause some unexpected behavior. You can do this by creating a new ObservableCollection<T> object and then adding the items from Globals.MapPageBaseClassList to it:
    
    foreach (var item in newPointsList)
    {
        // ...
    }
    var newMapPageBaseClassList = new ObservableCollection<BaseClass>(Globals.MapPageBaseClassList);
    newMapPageBaseClassList.InsertRange(0, Globals.PointControlList);
    Globals.MapPageBaseClassList = newMapPageBaseClassList;
    

    By doing this, you should be able to ensure that the MapPageBaseClassList is correctly updated every time a new point is added to the POINTS collection.

    Hope this will be helpful :-)


  2. Forrest Crawford 80 Reputation points
    2023-03-25T19:50:20.8033333+00:00

    Turns out the sortpoints was the culprit. I was reinitializing the POINTS variable but not re adding the collection changed event.

    
    
    
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.