wpf – ObservableCollection<T> binding through MVVM doesn’t update the view – Education Career Blog

I have the following simplified ViewModel

public class UserViewModel : IUserViewModel
{
    public DelegateCommand<object> NewUser { get; private set; }

    public ObservableCollection<UserInfo> UserList { get; set; }

    public UserViewModel( ) {
        NewUser = new DelegateCommand<object>( OnNewUser );

        this.UserList = new ObservableCollection<UserInfo>( );
        UserList.Add( new UserInfo( "Peter" );
        UserList.Add( new UserInfo( "Paul" );
        UserList.Add( new UserInfo( "Mary" );
    }

    private void OnNewUser( object parameter ) {
        UserInfo user = new UserInfo( "User"+DateTime.Now.ToLongTimeString(), 0, true, false, false );
        UserList.Add( user );
    }
}

This view model is the data context for a (simplified) view:

public partial class UserView : ViewBase
{
    public UserView( UserViewModel viewModel ) {
    InitializeComponent( );

    this.DataContext = viewModel;
    }
}

The view itself contains a ListBox that is bound to the UserList of the UserViewModel:

<ListBox ItemsSource="{Binding UserList}" DisplayMemberPath="UserID" />

When the view model is initialized it adds a user to the list. This user shows up in the list box. When afterwards the NewCommand is invoked, new users get added to the list. But the list box does not update with the new users.

I added a CollectionChanged handler to the view model as well as to the view. The views handler was added inside the constructor like this:

viewModel.UserList.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler( UserList_CollectionChanged );

EDIT

The command to add a new user to the collection is triggered by a button from a different view:

public class UserButtonBarViewModel : IUserButtonBarViewModel
{

    public UserButtonBarViewModel( IUserButtonBarView view, IUserViewModel mainModel ) {
        this.View = view;
        NewUser = mainModel.NewUser;
        this.View.Model = this;
    }

    public ICommand NewUser { get; private set; }

    public IUserButtonBarView View {get; private set; }
}

The UserButtonBarView looks like this:

<UserControl ...>
    <Button Command="{Binding NewUser}" Content="New user"/>
</UserControl>

And the view’s code behind:

public partial class UserButtonBarView : IUserButtonBarView
{

    public UserButtonBarView( ) {
        InitializeComponent( );
    }

    public IUserButtonBarViewModel Model {
        get {
            return DataContext as IUserButtonBarViewModel;
        }
        set {
            DataContext = value;
        }
    }
}

/EDIT

The interesting point is, that the handler in the view model was executed when a new user was added to the collection, but the view’s handler was not invoked.

Why gets the view’s handler not invoked as well? And why is the list box not updating itself when the collection in the view model is changed?

,

It sounds like you are creating a second copy of the ViewModel somewhere (probably in your ButtonViewModel) and your NewUser button is adding a user to one copy while the ListBox remains bound to another copy.

Can you post your NewUser command code?

,

Can you post the code that actually adds the new user? It seems like it might happen on a different thread than the UI? Try using Dispatcher.Invoke…

,

I think you need to use TwoWay binding.

<ListBox ItemsSource="{Binding UserList, Mode=TwoWay}" DisplayMemberPath="UserID" />

,

I saw that your UserList property has a setter – when you make changes to the user list are you clearing and adding to the current ObservableCollection, or creating a new one?

Leave a Comment