Infralution Support Forum Index Infralution Support
Support groups for Infralution products
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Respond to value-changes in the datasource

 
Post new topic   Reply to topic    Infralution Support Forum Index -> Virtual Tree Support
View previous topic :: View next topic  
Author Message
Harri
Guest





PostPosted: Mon Nov 21, 2005 7:23 am    Post subject: Respond to value-changes in the datasource Reply with quote

In our virtual tree, some of the rows displays the text and the value property of a data-object in two columns. We are using object-binding; three classes, (i.e. DataObjectRowBinding, DataObjectTextCellBinding, DataObjectValueCellBinding) arranging the display of the row, text and value. The value of our data-object can be changed outside the virtual tree while the virtual-tree displays this value. So there’s a ValueChange-event in the data-object in on which we can subscribe and unsubscribe.

Our data-object uses resources in our embedded system. Because the resources in our embedded system are pretty ‘costly’ we need to release them as soon as possible. We cannot relly on the garbage collector of dotnet (because it can take quite a while before it decides to dispose/release our data-objects). Therefore we need to dispose/release our data-objects explicitly. Also we need to unsubscribe from the ValueChange-event in the data-object (subscription to an event prevent the data-object of being disposed).

My question is which object (Row, CellWidget,..) is the proper place to subscribe and unsubscribe to/from the ValueChange-event in the data-object? And is there a way to control the disposal of this object and not rely on the dotnet garbage collector to call it?

Thank you in advance for your reply.
Harri
Back to top
Infralution



Joined: 28 Feb 2005
Posts: 5027

PostPosted: Mon Nov 21, 2005 9:13 am    Post subject: Reply with quote

Generally databinding notification is done through the IBindingList interface on the datasource collections. If your individual data objects have a ValueChange event then you can create a binding collection that attaches to this event of its contained objects and passes the notification on via IBindingList. Our base class BindingCollectionBase can make doing this fairly simple. However the disadvantage is that while the collection exists you will be attached to the events of the consituents - which you want to avoid.

You might want to consider changing your design so that notification of changes is not handled by the individual components and so the lifetime issues won't be so entwined with the notification mechanism (ie handle the change notification either at a collection level or have a separate agent responsible for generating change notifications).

If this is not an option the from what I can gather of your requirements you would probably want to handle subscribing/unsubscribing at the RowWidget level by creating a derived RowWidget class. Typically RowWidgets lifetime is linked directly to that of the currently displayed data ie RowWidgets only exist for those data items that are currently displayed. RowWidgets have a Dispose method that you could use to unsubscribe. While this would address the issue when using VirtualTree I think it would be better to consider some more general changes so that your architecture works regardless of the control being used to display your data - otherwise you'll have to craft a solution similar to this for each control used - and it simply may not be possible with some controls.
_________________
Infralution Support
Back to top
View user's profile Send private message Visit poster's website
Harri



Joined: 21 Nov 2005
Posts: 13

PostPosted: Tue Nov 22, 2005 6:46 am    Post subject: Reply with quote

Thank you for your answer.

However I do not fully understand your reply.
Our data-object just has a property named 'Value', and has an event 'ValueChanged'which is fired when the actual vlaue of this property changes. Subscribtion is the general way in dotnet to respond to changes of this data. I do not see the connection with IBindingList and why it should be responsible for generating this event; I think we have a misunderstanding here.

Moving the notification to another notification-class wouldn't make a difference I think. The problem remains that we have to 'release' the reference to our data-object as soon as it is not refered anymore. Then the notification-class needs to know if it's not referenced and release the data-object. Others should therefore subscribe and unsubscribe to this notification-class.

The way in dotnet to handle this is in my opinion using the Dispose-pattern. This is introduced to release 'unmanaged'-resources with which we are dealing. So I guess the RowWidget is then the place where the subscribtion/unsubscription should be done. As mentioned before, we cannot rely on the garbage-collector to call the dispose-method.
The question is then whether the dispose-method is called explicitly as soon as the RowWidget goes outoff scope?

Thanks again for your answer.
Harri
Back to top
View user's profile Send private message
Infralution



Joined: 28 Feb 2005
Posts: 5027

PostPosted: Tue Nov 22, 2005 7:52 am    Post subject: Reply with quote

OK I'll try again. Say you have a separate class (lets call it MyDataSource) which provides access to the items (lets call them MyDataItems) in your data source. The MyDataSource class can provide an ItemChanged event to let subscribers know when an a MyDataItem has changed. Each MyDataItem object contains a reference to the MyDataSource that it belongs to and can call an OnItemChanged method to get MyDataSource to raise the ItemChanged event to notify clients that it has changed.

Now you have decoupled the lifetime issue for MyDataItem from the need for clients to subscribe to a changed event. Since you don't have to hold references to every MyDataItem just to be notified of potential changes. In fact this is exactly the design of DataTables and DataRows in ADO.NET. The reason I mentioned the IBindingList interface is that this is typically the interface used to provide this sort of notification at a collection level. If your MyDataSource class is in fact a collection then you can just implement the IBindingList interface - which has a ListChanged event which you raise when either items in the collection change or items are added/removed from the collection (the event parameters tell clients exactly what the change is). If you use IBindingList to provide notifications then VirtualTree and other well behaved data bound controls will automatically update when the data is changed with no need for more code from you.

The answer to your last question is that the RowWidget.Dispose method is called as soon as the RowWidget is no longer displayed.
_________________
Infralution Support
Back to top
View user's profile Send private message Visit poster's website
Harri



Joined: 21 Nov 2005
Posts: 13

PostPosted: Wed Nov 23, 2005 6:48 am    Post subject: Reply with quote

Ok, thanks again for your quick reply.
I see now what you mean. I'm not familiar with IBindingList so thats why I didn't get your point the first time.
There's an event in IBindingList, i.e. ListChanged, which could be fired when one of the item's-property is changed. The ListChangeType in the arguments of the ListChangedEvent should be set to 'ItemChanged'.

I think it also means that the collection that implements IBindingList, should subscribe (and unsubscribe) to the item's-property-change event.
So also here, when is this class going to unsubscribe to these events?

Also my item has more properties that can change, and for each property there's a PropertyChange-event. I think when using the ListChanged-event, you cannot tell anymore which property is changed but only that one of the properties is changed and thus loosing (for us) valueable information (In our case, retrieving the value of properties might take a while because they need to come from a hardware-device).

Using the RowWidget, it works very nice at the moment (however I also want to try to get it working using IBindingList as you suggested).
In the RowWidget, I call the Tree.UpdateRow(row) to update the complete row.
However, I want to update just the applicable cell. Is there a way to do that (Tree.UpdateCell(cellWidget) or something similar) ?

Again thank you in advance
Harri
Back to top
View user's profile Send private message
Infralution



Joined: 28 Feb 2005
Posts: 5027

PostPosted: Wed Nov 23, 2005 8:52 am    Post subject: Reply with quote

Harri wrote:
I think it also means that the collection that implements IBindingList, should subscribe (and unsubscribe) to the item's-property-change event.
So also here, when is this class going to unsubscribe to these events?


No when you create the MyDataItem object you pass it a reference to the collection object (MyDataSource) - and it calls a method OnItemChanged to get it to raise the event. So MyDataSource does not have to subscribe to each object in the collection. This is also much more memory efficient because having a separate event subscription list on each item will be quite expensive.

Quote:

Also my item has more properties that can change, and for each property there's a PropertyChange-event. I think when using the ListChanged-event, you cannot tell anymore which property is changed but only that one of the properties is changed and thus loosing (for us) valueable information (In our case, retrieving the value of properties might take a while because they need to come from a hardware-device).


This is true if you use the standard IBindingList interface. You could derive your own ListChangedEventArgs class and add some information about what property has changed. When you raise the ListChanged event you would pass an instance of your derived class. That way clients that know about your specific implementation could extract the extra information - while standard IBindingList clients would still continue to work.

Quote:
Using the RowWidget, it works very nice at the moment (however I also want to try to get it working using IBindingList as you suggested).
In the RowWidget, I call the Tree.UpdateRow(row) to update the complete row.


If you already are in the RowWidget class you can just call its UpdateData method.

Quote:
However, I want to update just the applicable cell. Is there a way to do that (Tree.UpdateCell(cellWidget) or something similar) ?


You can find the CellWidget using GetCellWidget(column) and call its UpdateData method.
_________________
Infralution Support
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    Infralution Support Forum Index -> Virtual Tree Support All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group