Привязка ObservableCollection <T>через MVVM не обновляет представление - PullRequest
1 голос
/ 15 октября 2010

У меня есть следующая упрощенная 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 );
    }
}

Эта модель представления является контекстом данных для (упрощенного) представления:

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

    this.DataContext = viewModel;
    }
}

Само представление содержит ListBox, связанный с UserList модели UserViewModel:

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

Когда модель представления инициализируется, она добавляет пользователя в список. Этот пользователь появляется в списке. Когда впоследствии вызывается NewCommand, новые пользователи добавляются в список. Но список не обновляется с новыми пользователями.

Я добавил обработчик CollectionChanged как для модели вида, так и для вида. Обработчик представлений был добавлен в конструктор следующим образом:

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

[EDIT]

Команда добавления нового пользователя в коллекцию вызывается кнопкой из другого представления:

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

UserButtonBarView выглядит так:

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

И код представления позади:

public partial class UserButtonBarView : IUserButtonBarView
{

    public UserButtonBarView( ) {
        InitializeComponent( );
    }

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

[/ EDIT]

Интересно то, что обработчик в модели представления был выполнен, когда в коллекцию был добавлен новый пользователь, но обработчик представления не был вызван.

Почему обработчик представления также не вызывается? И почему окно списка не обновляется при изменении коллекции в модели представления?

Ответы [ 4 ]

3 голосов
/ 15 октября 2010

Похоже, что вы создаете вторую копию ViewModel где-то (возможно, в вашей ButtonViewModel), и ваша кнопка NewUser добавляет пользователя к одной копии, в то время как ListBox остается привязанным к другой копии.

Можете ли выопубликовать свой код команды NewUser?

0 голосов
/ 15 октября 2010

Я видел, что у вашего свойства UserList есть установщик - когда вы вносите изменения в список пользователей, вы очищаете и добавляете в текущую коллекцию ObservableCollection или создаете новую?

0 голосов
/ 15 октября 2010

Я думаю, вам нужно использовать привязку TwoWay.

<ListBox ItemsSource="{Binding UserList, Mode=TwoWay}" DisplayMemberPath="UserID" />
0 голосов
/ 15 октября 2010

Можете ли вы опубликовать код, который фактически добавляет нового пользователя? Похоже, что это может произойти в другом потоке, чем пользовательский интерфейс?Попробуйте использовать Dispatcher.Invoke ...

...