Print Page | Close Window

RelatedEntityList events

Printed From: IdeaBlade
Category: DevForce
Forum Name: DevForce 2009
Forum Discription: For .NET 3.5
URL: http://www.ideablade.com/forum/forum_posts.asp?TID=1618
Printed Date: 16-Apr-2025 at 10:28pm


Topic: RelatedEntityList events
Posted By: Sinnema
Subject: RelatedEntityList events
Date Posted: 15-Jan-2010 at 11:55pm
Hi,
 
We've constructed a pretty nifty bunch of classes that we call ObservableLists. These lists can do the following:
  • One can add new items to the lists.
  • The list than observes changes to the items in the list and tells all subscribed clients (using several mechanisms like INotifyProperyChanged, OnValueChanged, OnItemChanged, OnListChanged, etc.).
  • The different flavors are needed because there are incompatibilities between the different assemblies we use (like DevForce, WPF and .NET Collections).

The Classes we've written so far are:

  • ObservableList
  • FilteredObservableList
  • RelatedList
  • RelatedEntityList
  • AbstractSequenceHistoryList
  • AbstractIntersectingHistoryList

And there ViewModel counterparts. The list is still growing.

Now we have a problem with the RelatedEntityList of DevForce. It does a fine job of maintaining items correctly in the list but it does not tell our lists when changes in items of the list take place, other than CollectionChanged (items added, moved, deleted, etc) and PropertyChanged (a property of the list was changed).
 
We could add [AfterSet] interceptors for all properties of the items in the list but that would be like shooting a fly with a canon. Our ObservableLists depend on getting ValueChanged, ItemChanged, ListChanged and PropertyChanged events (overrides). Is there a way to get these kinds of events from the RelatedEntityList?
 
Regards,
Paul Sinnema
Diartis AG
 


-------------
Senior Developer at Diartis AG in Switzerland.



Replies:
Posted By: IdeaBlade
Date Posted: 19-Jan-2010 at 1:36pm
I'm not quite understanding what your specific issue is with the RelatedEntityList. How do you provide the functionality you desire (specifically, notice about internal changes to the contained items) when you get your data from other sources?



Posted By: Sinnema
Date Posted: 20-Jan-2010 at 10:54pm
In our Entities (the partial class) we use an ObservableProperty. This class notifies other of changes to its value. Our classes register with these properties and act accordingly. We use the AfterSet interceptor of DevForce to set the values in our properties. All this code for propagating etc. is generated using T4. At the moment we don't use any other sources than the entities of DevForce and I don't think that is going to change soon.

-------------
Senior Developer at Diartis AG in Switzerland.


Posted By: GregD
Date Posted: 21-Jan-2010 at 9:29am
It is the entity itself that must provide the initial notification that it has been changed; so it seems to me that any wrapper list class you create that is supposed to forward this notification must set up handlers for the individual entities' PropertyChanged events so that it (the wrapper list) can know this has occurred and so forward this information to its own event subscribers. This would be true no matter how you get the entities with which your wrapper list will be populated.


Posted By: Sinnema
Date Posted: 23-Jan-2010 at 3:27am
Hi Greg,
 
Your right. In the mean time we've cooked up a solution. Below's (part of) our code. We attach to the ListChanged event and act accordingly. This class is base on a class we call the ObservableList<T> which already has an implementation of the OnListChanged event (override). The class uses the RelatedEntityList<T> of DevForce and maintains its own list (that's why there is a RefillList()). The class is build using the principal: 'First make it work, than make it better and than make it fast'. We've proved it works.
 
Regards,
Paul Sinnema
Diartis AG
 
   public override void OnListChanged(object sender, ObservableListChangedEventArgs e)
  {
   if (m_SuspendItemChangedEvents == 0)
   {
    switch (e.Action)
    {
     case ObservableListChangedAction.Add:
      base.OnListChanged(sender, e);
      AttachPropertyChangedEvents(e.NewItems);
      break;
     case ObservableListChangedAction.Remove:
      DetachPropertyChangedEvents(e.OldItems);
      base.OnListChanged(sender, e);
      break;
     case ObservableListChangedAction.Replace:
     case ObservableListChangedAction.Move:
      DetachPropertyChangedEvents(e.OldItems);
      base.OnListChanged(sender, e);
      AttachPropertyChangedEvents(e.NewItems);
      break;
     case ObservableListChangedAction.None:
     case ObservableListChangedAction.Reset:
     case ObservableListChangedAction.Resync:
      base.OnListChanged(sender, e);
      break;
     default:
      throw new InvalidArgumentException("e.Action", e.Action);
    }
   }
  }
private void AttachChangedEvents()
  {
   if (m_RelatedEntityList != null)
   {
    m_RelatedEntityList.CollectionChanged += RelatedEntityListCollectionChanged;
    AttachPropertyChangedEvents(m_RelatedEntityList);
   }
  }
  private void AttachPropertyChangedEvents(IList list)
  {
   foreach (T item in list)
   {
    item.PropertyChanged += ItemPropertyChanged;
   }
  }
  private void DetachChangedEvents()
  {
   if (m_RelatedEntityList != null)
   {
    m_RelatedEntityList.CollectionChanged -= RelatedEntityListCollectionChanged;
    DetachPropertyChangedEvents(m_RelatedEntityList);
   }
  }
  private void DetachPropertyChangedEvents(IList list)
  {
   foreach (T item in list)
   {
    item.PropertyChanged -= ItemPropertyChanged;
   }
  }
 
   private void ItemPropertyChanged(object sender, PropertyChangedEventArgs e)
  {
   if (sender is T)
   {
    int index = IndexOf((T)sender);
    if (index >= 0)
    {
     this.OnItemChanged(sender, new ItemPropertyChangedEventArgs(this, sender, index, e.PropertyName));
    }
    RefillList();
   }
  }


-------------
Senior Developer at Diartis AG in Switzerland.


Posted By: IdeaBlade
Date Posted: 25-Jan-2010 at 11:22am
Thanks for sharing this, Paul.



Print Page | Close Window