I have two classes: Employee
and EmployeeGridViewAdapter
. Employee
is composed of several complex types. EmployeeGridViewAdapter
wraps a single Employee
and exposes its members as a flattened set of system types so a DataGridView can handle displaying, editing, etc.
I'm using VS's builtin support for turning a POCO into a data source, which I then attach to a BindingSource
object. When I attach the DataGridView
to the BindingSource
it creates the expected columns and at runtime I can perform the expected CRUD operations. All is good so far.
The problem is the collection of adapters and the collection of employees aren't being synchronized. So all the employees I create an runtime never get persisted. Here's a snippet of the code that generates the collection of EmployeeGridViewAdapter
's:
var employeeCollection = new List<EmployeeGridViewAdapter>();
foreach (var employee in this.employees)
{
employeeCollection.Add(new EmployeeGridViewAdapter(employee));
}
this.view.Employees = employeeCollection;
Pretty straight forward but I can't figure out how to synchronize changes back to the original collection. I imagine edits are already handled because both collections reference the same objects but creating new employees and deleting employees aren't happening so I can't be sure.
You could also considering using System.Collections.ObjectModel.ObservableCollection and wiring up it's CollectionChanged event. It could look something like this.
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;
}
};
Code assumes the following using statements.
using System.Collections.ObjectModel;
using System.Collections.Specialized;
If you need the IList interface you could also use System.ComponentModel.BindingList and wire up it's ListChanged event. It could look like this.
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;
}
};
Code assumes the following using statement.
using System.ComponentModel;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With