Help needed with BindingList<T> behaviour

Help needed with BindingList<T> behaviour

Old forum URL: forums.lhotka.net/forums/t/1217.aspx


Brian Criswell posted on Thursday, September 14, 2006

AAAAAAAAAGGGGHHHHH!!!!!!

Okay, got that out of my system.  Maybe I am just doing things wrong but....

I have been working on the ObjectListView, and one thing it does is have the individual ObjectView objects (the rows) implement IEditableObject.  What this should allow you to do is the following:

// Private fields
private Csla.ObjectListView _view;   // List of items to edit

private void addButton_Click(object sender, System.EventArgs e)
{
    using (EditForm edit = new EditForm())
    {
       ObjectView child = _view.AddNew();   // Automatically calls BeginEdit() on the ObjectView
       edit.ChildObject = (ChildObject)child.Object;

       if (edit.ShowDialog() == DialogResult.OK)
       {
          child.EndEdit();
       }
       else
       {
          child.CancelEdit();  // Would remove the new item from the underlying list except it throws an exception
       }
    }
}

The reason that it throws an exception is that the edit form has called BeginEdit on the child object and calls CancelEdit on the child object if it is closed through any other means than clicking OK.  This calls UndoChanges on the business object which calls OnUnknownPropertyChanged which calls OnPropertyChanged(string.Empty).  So, can you guess what the underlying BindingList<T> in BusinessListBase does when it sees that?  It fires a ListChangedType.Reset event!  It turns an unknown change on a single item into a reset of the entire list.  This causes an exception on the child.CancelEdit(); line because the ObjectListView has seen the ListChangedType.Reset and rebuilt the sorted list without the ObjectView that is in an edit.  So child no longer exists in the ObjectListView and it throws an IndexOutOfRange exception.

Any ideas of ways around this?  I am thoroughly frustrated.

Brian Criswell replied on Friday, September 15, 2006

Okay, so I got around that issue by implementing the code below.

private void addButton_Click(object sender, System.EventArgs e)
{
    using (EditForm edit = new EditForm())
    {
       edit.ChildObject = (ChildObject)_childList.AddNew();

       if (edit.ShowDialog() != DialogResult.OK)
       {
          _childList.Remove(edit.ChildObject);
       }
    }
}

This works, but it is unfortunate to use this method as being able to use ObjectListView.AddNew() would have suppressed all ListChanged events pointing to that row and the item would not have sorted until the entire edit was accepted or cancelled.

Copyright (c) Marimer LLC