BindingSourceNode, adding item to child collection programatically

BindingSourceNode, adding item to child collection programatically

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


ajj3085 posted on Tuesday, September 08, 2009

Hi,

I'm trying to solve a problem some of my users are having... very odd things that I can't reproduce (as usual). The problem is that sometimes it seems that what is in the grid on the screen doesn't match whats in memory. The grid can't remove the row because the "index is out of range," stuff like that.

So I'm trying to replace my manual binding / unbinding with BindingSourceNode. Seems to work fine (well, for me, the same as it was), but I'm hitting a problem I'm not sure how to get around.

I have a requirement where uses can rightclick one of the rows in the Addresses grid and say Copy as Billing, Copy as Shipping, etc.

This operation works fine, until I have, when I hit an EditLevelMismatch (Edit level mismatch in AcceptChanges) exception.

This is the code on how I add the row... the BSN says to only interact via that class with the BO... but I don't see how I can accomplish what I want in that case?

private void CloneAddressAs( string addressType ) {
UltraGridRow row;
ContactAddress address;

if ( AddressGrid.Selected.Rows.Count > 0 ) {
row = AddressGrid.Selected.Rows[ 0 ];

address = row.ListObject as ContactAddress;

if ( address != null ) {
address = address.GetCopy();
address.AddressType = "";
AddressesBindingSource.Add( address );
address.AddressType = addressType;
}
}
}

miguelcastro67 replied on Tuesday, September 08, 2009

I'm not sure I understand completely, but why don't you work only with your CSLA collection. If it's bound to a bindingsource it should carry through and onto the grid, should it not? Can you explain a little better?

ajj3085 replied on Wednesday, September 09, 2009

Because if you leave the BindingSource out of the equation, it gets confused, and your UI then gets confused.

JonnyBee replied on Wednesday, September 09, 2009

Hi,

I don't think this is related to the BindingSourceNode at all. It has to to do with databinding in WindowsForms and Csla.

The IndexOutOfRange can be triggered from a bug in FilteredbindingList/SortedBindingList on some rare occations. This bug is fixed so grab the lastest version of these classes in Csla 3.7.1 (or 3.8.0) and update your Csla version (triggered because the ItemChanged uses a faulty itemnumber in event to notify the grid of new item - so that when trying to delete the new item the itemnumber does not match the underlying list) .

You could try to add the following code to your BusinessListBase class:

    /// <summary>
    /// Adds a new item to the end of the collection.
    /// Uses DataPortal to create instance of Child object so the BO
    /// developer will no longer need to override this method in BO List
    /// </summary>
    /// <returns>
    /// The item that was added to the collection.
    /// </returns>
    /// <exception cref="T:System.InvalidCastException">
    /// The new item is not the same type as the objects contained in the <see cref="T:System.ComponentModel.BindingList`1"/>.
    /// </exception>
    protected override object AddNewCore()
    {
        var item = DataPortal.CreateChild<C>();
        Add(item);
        return item;
    }

    /// <summary>
    /// Adds an object to the end of the <see cref="T:System.Collections.ObjectModel.Collection`1"/>.
    /// </summary>
    /// <param name="item">The object to be added to the end of the <see cref="T:System.Collections.ObjectModel.Collection`1"/>. The value can be null for reference types.</param>
    public new void Add(C item)
    {
        // set parent reference
        item.SetParent(this);
        // set child edit level
        Core.UndoableBase.ResetChildEditLevel(item, this.EditLevel, false);
        // when an object is inserted we assume it is
        // a new object and so the edit level when it was
        // added must be set
        item.EditLevelAdded = _editLevel;
        base.Add(item);
        InsertIntoMap(item, IndexOf(item));
    }

These 2 functions makes the
Assuming that address.GetCopy() does a Clone() of the original object  I would also suggest that you make sure to call BindingSource or GridView EndEdit() method before you call GetCopy so that the EditState of the CurrentRow is not included in the copy.

/jonnybee


ajj3085 replied on Wednesday, September 09, 2009

I'm already on the latest 3.7 release, so that's not the issue.

Adding the BindingSourceNode is an attempt to correct the IndexOutOfRangeException, which I actually haven't been able to reproduce myself.

The EditLevelMismatchException is caused by the code I've posted..

I think I found a "solution," which is to just set the AddressType prior to adding the instance to the collecton. I'm still verifying if this works though, because I have rules over the collection, which is why I think I was doing it the way I was.

Copyright (c) Marimer LLC