从 ObservableCollection 中删除时未从 DataGrid 中删除项目

Item not removed from DataGrid when removing from ObservableCollection

当我从我的 ObservableCollection 中删除项目时,我很难更新数据网格。当我删除它们时,绑定到 DataGrid 的 ObservableCollection 中的项目被正确删除,但它们仍然出现在 DataGrid 中。

这是我的观点:

<Grid>
    <DataGrid x:Name="ContactsList" Margin="20" AutoGenerateColumns="False" IsReadOnly="True" CanUserResizeRows="False"
              CanUserResizeColumns="True" ColumnWidth="*" ItemsSource="{Binding Contacts, UpdateSourceTrigger=PropertyChanged, diag:PresentationTraceSources.TraceLevel=High}">
    </DataGrid>
</Grid>

(列填充在代码隐藏中)。

这是我的视图模型:

public class ContactsViewModel : BindableBase
{
    private readonly IRegionManager regionManager;
    private readonly IEventAggregator eventAggregator;
    private readonly IConfigurationContactsService contactsService;

    private readonly DelegateCommand<object> deleteContactCommand;

    private ObservableCollection<Contact> contactsCollection;
    private ICollectionView contactsView;

    public ContactsViewModel(IEventAggregator eventAggregator, IConfigurationContactsService contactsService, IRegionManager regionManager)
    {
        this.regionManager = regionManager;
        this.contactsService = contactsService;
        this.eventAggregator = eventAggregator;

        this.deleteContactCommand = new DelegateCommand<object>(this.DeleteContact, this.CanDeleteContact);

        this.contactsCollection = new ObservableCollection<Contact>(contactsService.GetContacts());
        this.contactsView = CollectionViewSource.GetDefaultView(this.contactsCollection);
    }

    public ICollectionView ContactsView
    {
        get { return this.contactsView; }
    }
    public ObservableCollection<Contact> Contacts
    {
        get { return this.contactsCollection; }
    }

    public ICommand DeleteContactCommand
    {
        get { return this.deleteContactCommand; }
    }

    private void DeleteContact(object ignore)
    {
        IList<Contact> selectedContacts = contactsService.GetSelectedContacts();
        foreach (Contact contact in selectedContacts)
        {
            if (contact != null)
            {
                contactsService.DeleteContact(contact);
            }
        }
        SetProperty<ObservableCollection<Contact>>(ref this.contactsCollection, new ObservableCollection<Contact>(contactsService.GetContacts()), "Contacts");
        // After this, the observable collection is updated correctly, but the datagrid does not delete the items.
    }
    private bool CanDeleteContact(object ignored)
    {
        return contactsService.GetSelectedContacts().Any();
    }       
}

我看不出错误在哪里。谁能发现错误?提前致谢。

编辑

这种观点有一个特点。有一个带有工具栏的主视图(删除按钮所在的位置),以及一个包含两个视图的 ContentTab 区域:视图 A、视图 B)。 DataGrid 位于视图 A 中,所有三个视图(A、B 和 MainView)都具有相同的视图模型:ContactsViewModel。

Observable 集合已经实现了 INotifyPropertyChanged,您不必再这样做:

public ObservableCollection<Contact> Contacts{ get;}


private void DeleteContact(object ignore)
{
    IList<Contact> selectedContacts = contactsService.GetSelectedContacts();
    foreach (Contact contact in selectedContacts)
    {
        if (contact != null)
        {
            contactsService.DeleteContact(contact);
            Contacts.Remove(contact);// HERE IS THE CHANGE
        }
    }
}

您只需删除旧项目,并添加新项目。不需要另一个实例。

编辑:

要添加新项目,请执行以下操作:

Contacts.Add(newContact);

编辑编辑:

您可能需要稍微修改一下删除,试试这个:

Contacts.Remove(Contacts.FirstOrDefault(c=c.Id == contact.Id)); // HERE IS THE CHANGE

我不知道您的联系人 class 中是否有 ID 属性,如果没有,请使用其他方式查找正确的联系人,例如。名字或姓氏

当您拥有 ICollectionView 属性 时,为什么要绑定到 ObservableCollection?。无论如何,这应该刷新对 ObservableCollection 的绑定:

private void DeleteContact(object ignore)
{
    IList<Contact> selectedContacts = contactsService.GetSelectedContacts();
    foreach (Contact contact in selectedContacts)
    {
        if (contact != null)
        {
            contactsService.DeleteContact(contact);
        }
    }
    contactsCollection = new ObservableCollection<Contact>(contactsService.GetContacts());
    this.OnPropertyChanged("Contacts");
}

如果 DataGrid 没有得到更新,您需要验证 contactsService.GetContacts() 方法 return 是否包含您期望的项目 return。

编辑: 您还需要确保视图绑定到执行 DeleteContact 方法的视图模型的同一实例。在视图模型的构造函数中放置一个断点,并确保它只被命中一次。然后你知道只有一个实例被创建并且你绑定到这个实例。