C# – ListBox bound to ObservableCollection doesn’t update

bindingclistboxobservablecollectionwpf

I am having trouble getting a ListBox binding to work as expected. I'm currently attempting to bind a ListBox to a singleton exposed ObservableCollection of items. The items are a separate class themselves. Currently, I am binding like this:

<Window x:Class="toxySharp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:classes="clr-namespace:MyApplication.Classes"
        Title="MainWindow" Height="325" Width="400"
        DataContext="{Binding Source={x:Static local:SingletonClass.Instance}}">

        <Grid x:Name="LayoutRoot">
            <ListBox x:Name="lstMyList" ItemsSource="{Binding Path=Objects, Mode=TwoWay}" DisplayMemberPath="Name" />
        </Grid>
</Window>

My singleton is a basic implementation like this:

public class SomeObject : INotifyPropertyChanged
{
    private Int32 m_vId;
    private String m_vName;

    public SomeObject() { }

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(String propName)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }
    }

    public Int32 Id
    {
        get { return this.m_vId; }
        set { this.m_vId = value; NotifyPropertyChanged("Id"); }
    }

    public String Name
    {
        get { return this.m_vName; }
        set { this.m_vName = value; NotifyPropertyChanged("Name"); }
    }
}

public class SingletonClass : INotifyPropertyChanged
{
    private static SingletonClass m_vInstance;
    private ObservableCollection<SomeObject> m_vObjects;

    private SingletonClass()
    {
        this.m_vObjects = new ObservableCollection<SomeObject>();
        for (int x = 0; x < 255; x++)
            this.m_vObjects.Add(new SomeObject() { Id = x, Name = String.Format("{0} - new object", x) });
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(String propName)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }
    }

    public static SingletonClass Instance
    {
        get
        {
            if (m_vInstance == null)
                m_vInstance = new SingletonClass();
            return m_vInstance;
        }
    }

    public ObservableCollection<SomeObject> Objects
    {
        get { return this.m_vObjects; }
        set { this.m_vObjects = value; NotifyPropertyChanged("Objects"); }
    }
}

Currently, the binding works on startup. The application will bind and properly show the names of each object. For example this is a test app doing the same implementation:
enter image description here

In my main actual application I have async methods being called (Socket stuff BeginConnect, BeginSend, etc.) that use callbacks that can update the collection. (It's a list of players so when certain packets are received the list is updated with their data.)

My problem is when the collection is updated inside one of the async callbacks it doesn't update on the list. The collection data is updated properly, setting a break in the main code anywhere shows the collection being updated but the listbox never updates to reflect the changes. So it just stays saying the same thing no matter what.

Did I overlook something?

I've tried using a CollectionViewSource as well to allow filtering and that has the same problem.

== EDIT ==

I've found the problem which lies in the singleton with how the collection is initialized. Instead of using the internal copy member when initializing the collection, I needed to use the exposed property to allow it to update the UI.

So using the following fixed it:

private SingletonClass()
{
    this.Objects = new ObservableCollection<SomeObject>();
    for (int x = 0; x < 255; x++)
        this.Objects.Add(new SomeObject() { Id = x, Name = String.Format("{0} - new object", x) });
}

However now that the list binding works I want to be able to filter this based on another property inside the object class. (In the example SomeObject). I have a boolean stating if the object is active. Trying to bind to a CollectionViewSource leads me back to the not updating problems. So is there a way to filter this manually and keep the ui updated?

Best Answer

My problem is when the collection is updated inside one of the async callbacks it doesn't update on the list.

Well thats the problem isnt it! Observable collections are not thread safe. You need to make them that way.

No TwoWay binding mode or UpdateSourceTrigger=PropertyChanged will help in this case as the problem lies with multi threading in your code...

Use this custom implementation of thread safe and faster observable collection for your ease...

Fast performing and thread safe observable collection

As far as INotifyPropertyChanged interface is concerned, its 'PropertyChangedevent is automatically dispatched to the UI thread. So any multithreaded context updating the properties of a class that implementsINotifyPropertyChanged` will update the GUI.

Let me know if this helps,

Related Topic