C# 将已包装对象集合与未包装对象集合同步

C# 将已包装对象集合与未包装对象集合同步,c#,collections,synchronization,C#,Collections,Synchronization,我有两个类:Employee和EmployeeGridViewAdapter员工由几个复杂类型组成EmployeeGridViewAdapter包装单个Employee并将其成员公开为一组扁平的系统类型,以便DataGridView可以处理显示、编辑等操作 我使用VS的内置支持将POCO转换为数据源,然后将其附加到BindingSource对象。当我将DataGridView附加到BindingSource时,它会创建预期的列,并且在运行时我可以执行预期的CRUD操作。到目前为止一切都很好 问题

我有两个类:
Employee
EmployeeGridViewAdapter
<代码>员工由几个复杂类型组成
EmployeeGridViewAdapter
包装单个
Employee
并将其成员公开为一组扁平的系统类型,以便DataGridView可以处理显示、编辑等操作

我使用VS的内置支持将POCO转换为数据源,然后将其附加到
BindingSource
对象。当我将
DataGridView
附加到
BindingSource
时,它会创建预期的列,并且在运行时我可以执行预期的CRUD操作。到目前为止一切都很好

问题是适配器集合和员工集合没有同步。因此,我创建的运行时中的所有员工都不会持久化。以下是生成
EmployeeGridViewAdapter
集合的代码片段:

        var employeeCollection = new List<EmployeeGridViewAdapter>();
        foreach (var employee in this.employees)
        {
            employeeCollection.Add(new EmployeeGridViewAdapter(employee));
        }
        this.view.Employees = employeeCollection;
var employeeCollection=new List();
foreach(此.employees中的var雇员)
{
添加(新的EmployeeGridViewAdapter(employee));
}
this.view.Employees=employeeCollection;

非常简单,但我不知道如何将更改同步回原始集合。我想编辑已经被处理了,因为两个集合引用了相同的对象,但是创建新员工和删除员工没有发生,所以我不能确定。

第一个问题似乎是您正在创建一个新列表并将数据绑定到该列表。添加元素时,这些元素将被添加到集合中,但原始员工列表保持不变

为了避免这种情况,您应该提供一个自定义集合类,将更改迁移回基础员工列表,或者在数据绑定到该列表之前连接适当的事件(在插入/删除时执行迁移)

要避免将可编辑集合绑定到网格时出现许多其他问题,应实现数据绑定接口,如下所述。这些界面的存在允许可视化控件通知底层集合有关操作,例如“插入已取消”(当用户中止新记录的输入时),并且同样允许信息以相反的方向流动(当集合或单个条目更改时更新UI)

首先,您需要在数据绑定集合中的各个项上至少实现IEditableObject、INotifyPropertyChanged和IDataErrorInfo,在您的示例中,这些项是EmployeeGridViewAdaper类

此外,您希望您的集合实现ITypedList和INotifyCollectionChanged。BCL包含一个BindingList实现,它提供了一个很好的起点。建议使用此列表而不是普通列表


我建议您对本主题进行详尽的介绍。

您也可以考虑使用和连接它的事件。它可能看起来像这样

        ObservableCollection<EmployeeAdapter> observableEmployees = 
                    new ObservableCollection<EmployeeAdapter>();

        foreach (Employee emp in employees)
        {
            observableEmployees.Add(new EmployeeAdapter(emp));
        }

        observableEmployees.CollectionChanged += 
            (object sender, NotifyCollectionChangedEventArgs e) =>
            {
                ObservableCollection<EmployeeAdapter> views = 
                        sender as ObservableCollection<EmployeeAdapter>;
                if (views == null)
                    return;
                switch (e.Action)
                {
                     case NotifyCollectionChangedAction.Add:
                        foreach (EmployeeAdapter view in e.NewItems)
                        {
                            if (!employees.Contains(view.Employee))
                                employees.Add(view.Employee);
                        }
                        break;
                     case NotifyCollectionChangedAction.Remove:
                        foreach (EmployeeAdapter view in e.OldItems)
                        {
                            if (employees.Contains(view.Employee))
                                employees.Remove(view.Employee);
                        }
                        break;
                    default:
                        break;
                }
            };
BindingList<EmployeeAdapter> empViews = new BindingList<EmployeeAdapter>();

foreach (Employee emp in employees)
{
    empViews.Add(new EmployeeAdapter(emp));
}

empViews.ListChanged +=
        (object sender, ListChangedEventArgs e) =>
            {
                BindingList<EmployeeAdapter> employeeAdapters = 
                        sender as BindingList<EmployeeAdapter>;
                if (employeeAdapters == null)
                    return;

                switch (e.ListChangedType)
                {
                    case ListChangedType.ItemAdded:
                        EmployeeAdapter added = employeeAdapters[e.NewIndex];
                        if (!employees.Contains(added.Employee))
                            employees.Add(added.Employee);
                        break;
                    case ListChangedType.ItemDeleted:
                        EmployeeAdapter deleted = employeeAdapters[e.OldIndex];
                        if (employees.Contains(deleted.Employee))
                            employees.Remove(deleted.Employee);
                        break;
                    default:
                        break;
                }
            };
如果你需要这个接口,你也可以使用它并连接它的事件。它可能看起来像这样

        ObservableCollection<EmployeeAdapter> observableEmployees = 
                    new ObservableCollection<EmployeeAdapter>();

        foreach (Employee emp in employees)
        {
            observableEmployees.Add(new EmployeeAdapter(emp));
        }

        observableEmployees.CollectionChanged += 
            (object sender, NotifyCollectionChangedEventArgs e) =>
            {
                ObservableCollection<EmployeeAdapter> views = 
                        sender as ObservableCollection<EmployeeAdapter>;
                if (views == null)
                    return;
                switch (e.Action)
                {
                     case NotifyCollectionChangedAction.Add:
                        foreach (EmployeeAdapter view in e.NewItems)
                        {
                            if (!employees.Contains(view.Employee))
                                employees.Add(view.Employee);
                        }
                        break;
                     case NotifyCollectionChangedAction.Remove:
                        foreach (EmployeeAdapter view in e.OldItems)
                        {
                            if (employees.Contains(view.Employee))
                                employees.Remove(view.Employee);
                        }
                        break;
                    default:
                        break;
                }
            };
BindingList<EmployeeAdapter> empViews = new BindingList<EmployeeAdapter>();

foreach (Employee emp in employees)
{
    empViews.Add(new EmployeeAdapter(emp));
}

empViews.ListChanged +=
        (object sender, ListChangedEventArgs e) =>
            {
                BindingList<EmployeeAdapter> employeeAdapters = 
                        sender as BindingList<EmployeeAdapter>;
                if (employeeAdapters == null)
                    return;

                switch (e.ListChangedType)
                {
                    case ListChangedType.ItemAdded:
                        EmployeeAdapter added = employeeAdapters[e.NewIndex];
                        if (!employees.Contains(added.Employee))
                            employees.Add(added.Employee);
                        break;
                    case ListChangedType.ItemDeleted:
                        EmployeeAdapter deleted = employeeAdapters[e.OldIndex];
                        if (employees.Contains(deleted.Employee))
                            employees.Remove(deleted.Employee);
                        break;
                    default:
                        break;
                }
            };

@肯尼斯:你做了什么来解决你的问题?把ObserviewModelCollection解决方案应用到你的问题上怎么样。