BusinessListBase.SetItem Bug

BusinessListBase.SetItem Bug

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


simon_may posted on Thursday, March 29, 2012

On the last line of this method it calls

OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, child, index));

Which raises the collection change event. However it is passing NotifyCollectionChangedEventArgs containing NotifyCollectionChangedAction.Remove. I believe that this causes Wpf to remove the item from the bound Listbox. Surely this should be NotifyCollectionChangedAction.Replace.

I ammended CSLA 4.3.10 source and it certainly solved my problem. Of course, I dont want to use this unless the fix is properly sanctioned

 

JonnyBee replied on Thursday, March 29, 2012

It is a bug. Added to bugtracker:

http://www.lhotka.net/cslabugs/edit_bug.aspx?id=1038

simon_may replied on Thursday, March 29, 2012

Jonny

Oh life is not as simple as we would like. It turns out that NoifyCollectionChangedEventArgs constructor will not accept an Action of NotifyCollectionChangedAction.Replace, it will only accept Add, Remove and Reset. In my testing an exception was thrown that my UI framework was swallwoing (I didnt see it unitl i was looking at a log).

I think that you can either leave out the notification altogether and the developer has to refresh the binding or use the Reset action, preferable. If you change it to Reset be sure to set the Index to -1. I didnt see SetItem failing visually as I had raised a PropertyChanged event on the BusinessObject's collection property as well in my initail attempt to make it work.

Microsoft documentation can be misleading (aka lying) :-)


Simon.

JonnyBee replied on Thursday, March 29, 2012

Another possibility:

Call remove on old child when raiselistchangedevents is false and call setitem after it's reset to true. (reverse order from today).

simon_may replied on Thursday, March 29, 2012

Then the item ends up in the DeleteList not something that I want. In my case I am replacing the item with a modified version of itself.

RockfordLhotka replied on Thursday, March 29, 2012

The events raised should match those raised by a standard ObservableCollection<T>. Whatever we want or don't want is immaterial - only the standard behavior matters.

It should be easy enough to monitor the events raised by a standard ObservableCollection and mirror them. In fact, I thought that's what I did with this implementation - but perhaps I did make a mistake in the code.

JonnyBee replied on Thursday, March 29, 2012

It is a bug:

Using ObservableCollection<T>
Action:Replace, NewStartingIndex:1, OldStartingIndex:1

Using Csla.BusinessListBase<C, T>
Action:Remove, NewStartingIndex:-1, OldStartingIndex:1

Code:

      var list = ItemList.New();
      list.CollectionChanged += (o, e) =>
                                  {
                                    Console.WriteLine("Action:{0}, NewStartingIndex:{1}, OldStartingIndex:{2}", e.Action.ToString(), e.NewStartingIndex, e.OldStartingIndex);
                                  };
      list[1] = new Item() {Id = 5, Name = "XYZZY"};
      Console.ReadLine();

JonnyBee replied on Thursday, March 29, 2012

Changing the sequence as described will make the correct listchanged event to occur.

JonnyBee replied on Thursday, March 29, 2012

Changes checked in to repository for Csla 4.3.x and 4.5

Copyright (c) Marimer LLC