Thursday, March 26, 2009

Working with WPF DataGrid - Part 4

The ObservableCollection has a CollectionChanged event that can be used to trace changes to the collection binded to the DataGrid. We will be using the CollectionChanged event and the ItemEndEdit event of the ObservableCollection class to support CRUD operations on the sample.

To add handlers for the CollectionChanged and ItemEndEdit event for the EmployeeCollection used in our sample, I have modified the EmployeeDataProvider class GetEmployees method as

public ObservableEmployee GetEmployees()

{

ObservableEmployee employeeCollection = new ObservableEmployee(EmployeeFactory.GetEmployees());

employeeCollection.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler((x, y) =>

{

if (y.Action == NotifyCollectionChangedAction.Remove)

{

foreach (object item in y.OldItems)

EmployeeFactory.Remove(Translator.ViewToBusiness(item as UIEmployee));

}

});

employeeCollection.ItemEndEdit += new UIEmployee.ItemEndEditEventHandler((x) => EmployeeFactory.Update(Translator.ViewToBusiness(x as UIEmployee)));

return employeeCollection;

}

The DataGrid is able to perform an atomic commit of the row which is currently being edited; this is made possible if the bound items implement the IEditableObject interface which exposes BeginEdit, EndEdit, and CancelEdit methods. Typically, an object implementing this interface would return to its state at the point when the BeginEdit method was called as a response to the CancelEdit method being invoked. However, in this instance, we are not really concerned about being able to cancel edits; all we really need to know is when the user has finished editing a row. This is indicted when the DataGrid invokes EndEdit on our bound item. In order to notify the EmployeeDataProvider that EndEdit has been invoked on one of the objects in the collection; the UIEmployee implements the IEditableObject as given below.

public class UIEmployee : INotifyPropertyChanged, IEditableObject

{

//Previous code goes here

public delegate void ItemEndEditEventHandler(IEditableObject sender);

public event ItemEndEditEventHandler ItemEndEdit;

#region IEditableObject Members

public void BeginEdit() { }

public void CancelEdit() { }

public void EndEdit()

{

if (ItemEndEdit != null)

ItemEndEdit(this);

}

#endregion

}

The event is handled for all the items in the collection as

public class ObservableEmployee : ObservableCollection<UIEmployee>

{

//Previous code goes here

protected override void InsertItem(int index, UIEmployee item)

{

base.InsertItem(index, item);

item.ItemEndEdit += new UIEmployee.ItemEndEditEventHandler((x) =>

{

if (ItemEndEdit != null)

ItemEndEdit(x);

});

}

}

That completes the code for the CRUD operations on the DataGrid. The next part we’ll see how to implement sorting on the datagrid.

1 comment:

Anonymous said...

Very nice work-through, however I get an error when adding the
protected override void InsertItem(int index, ContextUI item)
{
base.InsertItem(index, item);
item.ItemEndEdit += new ContextUI.ItemEndEditEventHandler((x) =>
{

if (ItemEndEdit != null)

ItemEndEdit(x);

});
}

code to the ObservableCollection class, the complier says that "the name ItemEndEdit does not exist in the current context". Since I no nothing about lambda expressions I can't figure out what is wrong. Can you help?