Collection.RemoveAt, Infragistics DataGrid

Posts   
 
    
caseyry
User
Posts: 79
Joined: 25-Feb-2005
# Posted on: 20-Jul-2005 17:46:08   

I know that Infragistics UltaWinGrid isn't a favorite topic of Frans's, smile , but I have a question about removing an Entity from a collection that is bound to an UltraWinGrid.

Basically, after a Collection has been bound to an UltraWinGrid, can I still remove an entity from the collection and have the Grid update itself?

I would have thought this would work since LLBL Gen Pro would "notify" the Grid that an entity has been removed.

Here's the code I'm using:


            foreach (int index in IndexOfRecordsToRemove)

                if (index >= 0)
                {
                    _harvestMenuDS.RemoveAt(index);
                    _displayGrid.Rows[index].Delete(false);                 
                }

Where _harvestMenuDS is a Collection object and _displayGrid is an UltraWinGrid.

I've tried just using the .RemoveAt() withouth also calling UltraWinGrid's delete method. But that doesn't work either.

I'm using self servicing; LLBL Gen Pro version 1.0.2004.2, released on June 5, 2005 and Infragistics NetAdvantage 2005 vol 2.

Thanks, -Ryan Casey

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 20-Jul-2005 19:05:23   

Ah the UltraWinGrid wink

RemoveAt does signal the grid, by calling IBindingList.ListChanged(index, ListChangeType.ItemDeleted), which is an event a grid will bind to to get notifications if something was removed/added etc.

btw, does: _harvestMenuDS.Remove(_harvestMenuDS[index]); work instead?

Frans Bouma | Lead developer LLBLGen Pro
caseyry
User
Posts: 79
Joined: 25-Feb-2005
# Posted on: 20-Jul-2005 19:31:49   

Otis wrote:

RemoveAt does signal the grid, by calling IBindingList.ListChanged(index, ListChangeType.ItemDeleted), which is an event a grid will bind to to get notifications if something was removed/added etc.

That's what I thought...

Otis wrote:

btw, does: _harvestMenuDS.Remove(_harvestMenuDS[index]); work instead?

Nope. Though the ListChanged event is firing:


_harvestMenuDS.ListChanged += new System.ComponentModel.ListChangedEventHandler(_harvestMenuDS_ListChanged);



private void _harvestMenuDS_ListChanged(object sender, System.ComponentModel.ListChangedEventArgs e)
{
  Console.WriteLine("List Changed: " + e.ListChangedType + "; OldIndex: " + e.OldIndex);
}

And the output is: List Changed: ItemDeleted; OldIndex: -1

Hmmm...Should the e.OldIndex be the Index of the item removed from the collection?

Thanks, -Ryan Casey

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 20-Jul-2005 20:16:35   

-1 ? Huh, I pass the index passed into RemoveAt to the event! Strange...

Frans Bouma | Lead developer LLBLGen Pro
caseyry
User
Posts: 79
Joined: 25-Feb-2005
# Posted on: 20-Jul-2005 20:21:18   

Otis wrote:

-1 ? Huh, I pass the index passed into RemoveAt to the event! Strange...

So, does point to the bug being with the LLBL Gen Pro code?

Should I install the latest runtimes, templates, etc. from the web site? Or is there additional information that would be helpful?

I couldn't find documentation on what OldIndex should be in MS's IBindingList documentation, so I wasn't sure if this was an Infragistics bug or an LLBL Gen Pro issue...

Thanks.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 20-Jul-2005 21:30:53   

caseyry wrote:

Otis wrote:

-1 ? Huh, I pass the index passed into RemoveAt to the event! Strange...

So, does point to the bug being with the LLBL Gen Pro code?

I've no idea, I'll check it out first thing tomorrow. Looking at the code (pasted below) it shouldn't be.

Should I install the latest runtimes, templates, etc. from the web site? Or is there additional information that would be helpful?

You're using 1.0.2004.2, which hasn't had a revision in that area, so it should be fine.

RemoveAt method:


/// <summary>
/// Removes the IEntity instance at the index given.
/// </summary>
/// <param name="index">Index in list to remove the element.</param>
public new void RemoveAt(int index)
{
    TraceHelper.WriteLineIf(TraceHelper.GeneralSwitch.TraceInfo, "EntityCollectionBase.RemoveAt", "Method Enter");
    IEntity entityToRemove = (IEntity)List[index];
    TraceHelper.WriteIf(TraceHelper.GeneralSwitch.TraceVerbose, ((EntityBase)entityToRemove).GetEntityDescription(TraceHelper.GeneralSwitch.TraceVerbose), "Entity to Remove Description");
    TraceHelper.WriteIf(TraceHelper.GeneralSwitch.TraceVerbose, index, "Index passed in.");

    if(_isSorted)
    {
        _contentInOriginalOrder.RemoveAt(_contentInOriginalOrder.IndexOf(List[index]));
    }
    else
    {
        _contentInOriginalOrder.RemoveAt(index);
    }

    if(BeforeRemove!=null)
    {
        BeforeRemove(entityToRemove, new EventArgs());
    }

    if(_containingEntity!=null)
    {
        entityToRemove.UnsetRelatedEntity(_containingEntity, _containingEntityMappedField);
    }

    base.RemoveAt(index);
    OnListChanged(index, ListChangedType.ItemDeleted);

    // remove subscribtion to the changed event.
    entityToRemove.EntityContentsChanged -= new EventHandler(EntityInListOnEntityContentsChanged);

    TraceHelper.WriteLineIf(TraceHelper.GeneralSwitch.TraceInfo, "EntityCollectionBase.RemoveAt", "Method Exit");
}

OnListChange method:


/// <summary>
/// Called when the List is changed and the event should be raised.
/// </summary>
/// <param name="index">Index of object causing the list change</param>
/// <param name="typeOfChange">The type of change to reflect to subscribers</param>
protected virtual void OnListChanged(int index, ListChangedType typeOfChange)
{
    if(ListChanged!=null)
    {
        ListChanged(this, new ListChangedEventArgs(typeOfChange, index));
    }
}

for completeness, also remove method:


/// <summary>
/// Remove given IEntity from the list.
/// </summary>
/// <param name="entityToRemove">Entity object to remove from list.</param>
public void Remove(IEntity entityToRemove)
{
    TraceHelper.WriteLineIf(TraceHelper.GeneralSwitch.TraceInfo, "EntityCollectionBase.Remove", "Method Enter");
    TraceHelper.WriteIf(TraceHelper.GeneralSwitch.TraceVerbose, ((EntityBase)entityToRemove).GetEntityDescription(TraceHelper.GeneralSwitch.TraceVerbose), "Entity to Remove Description");
    int index = List.IndexOf(entityToRemove);
    if(index >=0)
    {
        if(BeforeRemove!=null)
        {
            BeforeRemove(entityToRemove, new EventArgs());
        }
        List.Remove(entityToRemove);
        _contentInOriginalOrder.Remove(entityToRemove);

        if(_containingEntity!=null)
        {
            entityToRemove.UnsetRelatedEntity(_containingEntity, _containingEntityMappedField);
        }

        OnListChanged(index, ListChangedType.ItemDeleted);

        // remove subscribtion to the changed event.
        entityToRemove.EntityContentsChanged -= new EventHandler(EntityInListOnEntityContentsChanged);
    }

    TraceHelper.WriteLineIf(TraceHelper.GeneralSwitch.TraceInfo, "EntityCollectionBase.Remove", "Method Exit");
} 

Frans Bouma | Lead developer LLBLGen Pro
caseyry
User
Posts: 79
Joined: 25-Feb-2005
# Posted on: 21-Jul-2005 05:06:40   

Well, as the "Pragmatic Programmers" would say, select wasn't broken. stuck_out_tongue_winking_eye At least not removing entities from the collection.

I was able to work through the issue. Basically, I think what was happening is that the collection was removing different entities than what I intended to be removed.

Correct me if I'm wrong but my orginal code below,



           foreach (int index in IndexOfRecordsToRemove)
                if (index >= 0)
                {
                    _harvestMenuDS.RemoveAt(index);         
                }

was removing the wrong entities. The initial entity to remove was correct, but after that one was removed, the wrong entities were removed from the collection since the index of the remaining entities would be different since there was now 1 less entity in the collection.

Now, I've built a tmp collection of entities to remove, then on the original collection I want to remove entities from, I do a Remove(Entity) which works well.

As far as the OldIndex returning -1 in the ListChanged event, I don't know about that. smile . But the entities are being removed now and the Grid actually shows the correct list. If I can help you debug this futher, please let me know.

Otis wrote:

for completeness, also remove method:


/// <summary>
/// Remove given IEntity from the list.
/// </summary>
/// <param name="entityToRemove">Entity object to remove from list.</param>
public void Remove(IEntity entityToRemove)
{
    TraceHelper.WriteLineIf(TraceHelper.GeneralSwitch.TraceInfo, "EntityCollectionBase.Remove", "Method Enter");
    TraceHelper.WriteIf(TraceHelper.GeneralSwitch.TraceVerbose, ((EntityBase)entityToRemove).GetEntityDescription(TraceHelper.GeneralSwitch.TraceVerbose), "Entity to Remove Description");
    int index = List.IndexOf(entityToRemove);
    if(index >=0)
    {

...


Just a suggestion, but it might be helpful to have a Trace statement if the value of index is < 0 or what the value of index is as the Trace statement in RemoveAt() does.

Thanks again, I always appreciate the quick responses and it makes me feel better when the bug was not in the LLBLGen Pro code.

-Ryan Casey

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 21-Jul-2005 09:54:24   

caseyry wrote:

Well, as the "Pragmatic Programmers" would say, select wasn't broken. stuck_out_tongue_winking_eye At least not removing entities from the collection.

I was able to work through the issue. Basically, I think what was happening is that the collection was removing different entities than what I intended to be removed.

Correct me if I'm wrong but my orginal code below,



           foreach (int index in IndexOfRecordsToRemove)
                if (index >= 0)
                {
                    _harvestMenuDS.RemoveAt(index);         
                }

was removing the wrong entities. The initial entity to remove was correct, but after that one was removed, the wrong entities were removed from the collection since the index of the remaining entities would be different since there was now 1 less entity in the collection.

Oh of course! sunglasses . heh, one of those issues which can keep you busy for days!. simple_smile

Now, I've built a tmp collection of entities to remove, then on the original collection I want to remove entities from, I do a Remove(Entity) which works well.

Yes, I think that's a better solution.

As far as the OldIndex returning -1 in the ListChanged event, I don't know about that. smile . But the entities are being removed now and the Grid actually shows the correct list. If I can help you debug this futher, please let me know.

Well, as you can see, there's no way the index gets modified, in the call chain so I don't know what causes the -1 to be honest. simple_smile I'll do a test simple_smile

Otis wrote:

for completeness, also remove method:


/// <summary>
/// Remove given IEntity from the list.
/// </summary>
/// <param name="entityToRemove">Entity object to remove from list.</param>
public void Remove(IEntity entityToRemove)
{
    TraceHelper.WriteLineIf(TraceHelper.GeneralSwitch.TraceInfo, "EntityCollectionBase.Remove", "Method Enter");
    TraceHelper.WriteIf(TraceHelper.GeneralSwitch.TraceVerbose, ((EntityBase)entityToRemove).GetEntityDescription(TraceHelper.GeneralSwitch.TraceVerbose), "Entity to Remove Description");
    int index = List.IndexOf(entityToRemove);
    if(index >=0)
    {

...


Just a suggestion, but it might be helpful to have a Trace statement if the value of index is < 0 or what the value of index is as the Trace statement in RemoveAt() does.

I'll add it to the list simple_smile

Thanks again, I always appreciate the quick responses and it makes me feel better when the bug was not in the LLBLGen Pro code.

Thank you! smile

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 21-Jul-2005 11:47:41   

OldIndex seems to be -1 always. The NewIndex property contains the index of the action. This is because I never set the OldIndex, I pass in the index as newIndex.

I'll now do some testing with a grid, to see if I can reproduce your issue.

(edit): RemoveAt(1) works with a normal datagrid, it removes the row visually, so no re-draw required. I'll see if that's also the case when I set oldindex to 1 and newindex to -1.

(edit): ok, setting newindex to -1 and oldindex to 1 (which IMHO is correct) gives an exception in the currencymanager that the index is out of range... i.o.w.: newindex should apparently be the index of the item it had BEFORE the action (though you'd expect the oldindex to have that value).

(edit): having both set to the same index works fine. Can I send you this temp build to try it out on infragistics grid v2005.2 ? I don't have that grid here. scratch that. The docs of ListChangedType say: ItemDeleted: An item deleted from the list. ListChangedEventArgs.NewIndex contains the index of the item that was deleted. So oldindex isn't used. if infragistics uses it, it's non-standard.

Frans Bouma | Lead developer LLBLGen Pro
caseyry
User
Posts: 79
Joined: 25-Feb-2005
# Posted on: 21-Jul-2005 14:49:13   

Otis wrote:

So oldindex isn't used. if infragistics uses it, it's non-standard.

I don't think they are, or if they are things appear to be working properly.

Thanks.