Qerts
Qerts

Reputation: 1005

ItemsSource binding do not update values

I need to make list of items. I binded collection of users to listbox. Everything works quite well, but items in listbox aren't updated in real time. They aren't updated at all by this binding. So when I remove any user from the list, listbox isn't updated even if its source is correctly changed.

Source is located in data view model at path DataViewModel.Instance.AllUsers; Whenever I add to this list new item or remove one, layout does not update. Other bindings work well. I tried to update listbox layout, to raise event of source update, other way of adding/removing items, but nothing worked.

I tried to debug binding, but I have too many bindings to find the error.

Thanks in advance for any useful advice.

Listbox:

<ListBox x:Name="ListboxUsers" ItemsSource="{Binding Path=AllUsers, Mode=OneWay}" Grid.Column="1" Margin="0" Grid.Row="5" Background="DimGray" BorderThickness="0" Visibility="Hidden" SelectionChanged="ListboxUsers_SelectionChanged"/>

Code-behind:

CatalogueGrid.DataContext = DataViewModel.Instance;    //whole view model added as datacontext

DataViewModel class:

public class DataViewModel : INotifyPropertyChanged
{
    private static DataViewModel _dataViewModel;

    private Collection<UserModel> allUsers;
    public Collection<UserModel> AllUsers
    {
        get
        {
            return allUsers;
        }
        set
        {
            allUsers = value;
            NotifyPropertyChanged("AllUsers");
        }
    }


    private DataViewModel()
    {
        AllUsers = new Collection<UserModel>();
    }    

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(string info)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(info));
        }
    }
    .
    .
    .

}

Upvotes: 4

Views: 10247

Answers (3)

SamTh3D3v
SamTh3D3v

Reputation: 9944

use ObservableColLection instead if Collection wich implements the INotifyCollectionChanged Interface :

private ObservableCollection<UserModel> allUsers;
public ObservableCollection<UserModel> AllUsers
{
    get
    {
        return allUsers;
    }
    set
    {
        allUsers = value;
        NotifyPropertyChanged("AllUsers");
    }
}

Upvotes: 12

O. R. Mapper
O. R. Mapper

Reputation: 20731

You have bound your listbox to a Collection<T> - that is just a list, which does not issue any notifications to bound properties that its contents has changed. Hence, your listbox cannot possibly know when the collection has changed.

Instead, you can use the ObservableCollection<T> class (or, more precisely, any collection that also implements INotifyCollectionChanged), and changes will be automatically propagated to the listbox.

Note that your property does not have to be typed as ObservableCollection<T>, you can also just declare your public property as IEnumerable<T> or IList<T>; the binding will find out on its own whether the returned class also implements INotifyCollectionChanged. Like this, you are free to replace your actual underlying collection class later on, for example with a ReadOnlyObservableCollection<T>, in case you want to disallow changes from the outside.

Speaking of this, a note on your code: You have provided your AllUsers property with a setter. This may lead to undesired consequences, as you open up possibilities for some other code to set the property to null, which (depending on the rest of your code) might lead to exceptions. Unless you actually want to allow assigning new values, for the ItemsSource property binding, a read-only property is fully sufficient, as long as the returned collection object implements INotifyCollectionChanged.

Upvotes: 3

BradleyDotNET
BradleyDotNET

Reputation: 61349

For changes to the collection to propagate to the UI, the collection class needs to implement INotifyCollectionChanged.

A very useful class that already implements this is ObservableCollection<T> (MSDN). Use that instead of Collection<T>.

Upvotes: 5

Related Questions