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 

Manual refresh required after adding new data object?

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



Joined: 22 Apr 2008
Posts: 31

PostPosted: Wed Apr 23, 2008 3:41 am    Post subject: Manual refresh required after adding new data object? Reply with quote

Any idea why I seem to have to manually invoke a refresh of the grid after programmatically adding an item to the underlying collection it is bound to? I currently have to programmatically call Row.UpdateChildren (or maybe refresh or other methods) or I have to do something at run time like expanding or collapsing nodes to get the new item in the collection to show in the control.

We are using LLBLGEN and the datasource is an EntityCollection<T> but under the hood it gets bound to an EntityView which does implement IBindingList. Based on the comments in Row.UpdateChildren, I would think this would happen automatically.


Code:

private void AddNewChildPermission()
        {
            if (null != this.CurrentPermission)
            {
                SecActivityEntity permission = new SecActivityEntity();
                //no need to set id client side, just let it set from server save
                //permission.SecActivityId = --_permissionId;
                permission.Name = "New permission";
                permission.Description = null;
                permission.SecActivity = this.CurrentPermission;
                this.CurrentPermission.SecActivity_.Add(permission);

                // this seems to be required to get the tree to immediately reflect the change
                // even though tree is bound to an EntityView which implements IBindingList
                Tree.SelectedRow.UpdateChildren(false, false);               
            }
        }

        private SecActivityEntity CurrentPermission
        {
            get
            {
                //return permissionsBindingSource.Current as SecActivityEntity;
                return Tree.SelectedRow.Item as SecActivityEntity;
            }
        }
Back to top
View user's profile Send private message
Infralution



Joined: 28 Feb 2005
Posts: 5027

PostPosted: Wed Apr 23, 2008 6:32 am    Post subject: Reply with quote

Each collection (at each level of the tree) that is bound to needs to support IBindingList for the update to happen automatically. So if the children for a row of the tree were bound to the CurrentPermission.SecActivity collection and this collection supports IBindingList then VirtualTree will automatically update (assuming that the collection actually raises the ListChanged event).

To check what is happening you could try attaching an event handler to the collections ListChanged event yourself and verify that the collection is actually raising the event eg

Code:
IBindingList bindingList = this.CurrentPermission.SecActivity as IBindingList;
bindingList += new ListChangedEventHandler(OnListChanged);
this.CurrentPermission.SecActivity_.Add(permission);


Then put a break point in the OnListChanged handler and verify it is called.
_________________
Infralution Support
Back to top
View user's profile Send private message Visit poster's website
thnk2wn



Joined: 22 Apr 2008
Posts: 31

PostPosted: Sat Apr 26, 2008 10:13 pm    Post subject: ListChanged Reply with quote

Well ListChanged is firing; not sure why UpdateChildren is not getting called automatically when it appears all the standard list interfaces are there. If needed I can look at deriving from VirtualTree and perhaps wiring to automatically make the tree refresh when adding to the underlying list.

[/url]
Back to top
View user's profile Send private message
Infralution



Joined: 28 Feb 2005
Posts: 5027

PostPosted: Sat Apr 26, 2008 11:24 pm    Post subject: Reply with quote

Does the code I posted originally compile and run ie:

Code:
IBindingList bindingList = this.CurrentPermission.SecActivity as IBindingList;
bindingList += new ListChangedEventHandler(OnListChanged);
this.CurrentPermission.SecActivity_.Add(permission);


I wanted to verify that the collection does support the IBindingList interface and events are fired through it - as this is the way VirtualTree will connect to the event.
_________________
Infralution Support
Back to top
View user's profile Send private message Visit poster's website
thnk2wn



Joined: 22 Apr 2008
Posts: 31

PostPosted: Sun Apr 27, 2008 12:47 am    Post subject: Reply with quote

Sorry I missed the IBindingList cast. Well I cannot directly cast SecActivity_ to IBindingList but I can cast SecActivity_.DefaultView to an IBindingList, and that fires ListChanged correctly as well.

Code:

IBindingList bl = this.CurrentPermission.SecActivity_.DefaultView as IBindingList;
bl.ListChanged += OnListChanged;


SecActivity_ (SecActivityCollection the children) inherits from LGEN's EntityCollection which implements IList, IListSource, IEnumerable and related. It does not implement IBindingList directly because the entity collections themselves are never directly bound to anything. The EntityCollection's DefaultView (of type EntityView) is what gets bound to under the hood, and EntityView implements IBindingList.

Same paradigm as DataTables where UI controls actually bind to DataTable's DefaultView. If the virtual tree calls update children automatically in the case of binding to a dataset, I would expect it to do the same here as all the same typical binding interfaces and view behaviors are at play here in similar fashion.

If needed I can try to send sample code though it will take a bit to mock up a stripped down version of the app w/DB removed etc.

Assuming the control does not pick up on IBindingList from the DefaultView and I have to go at this manually, how can I easily do that in generic fashion? I do not want to have to do this manually for each instance of the control I use. I currently have a custom class deriving from VirtualTree. I do not see any kind of "NodeAdded" event where I could hook in and manually call UpdateChildren in our derived control. I suppose I could get at the datasource and the control's RowBindings and use reflection to get every child list and wire list changed and call updatechildren...but that sounds like no fun at all. Very Happy
Back to top
View user's profile Send private message
Infralution



Joined: 28 Feb 2005
Posts: 5027

PostPosted: Sun Apr 27, 2008 10:46 pm    Post subject: Reply with quote

If SecActivity_ does not implement IBindingList then that would explain why VirtualTree is not attaching to the ListChanged event .

Probably the solution is to override the GetChildrenForRow method and instead of returning an EntityCollection return the DefaultView. This is similar to what our DataSet RowBindings when binding to DataTables. Virtual Tree will then be able to bind via the IBindingList interface.
_________________
Infralution Support
Back to top
View user's profile Send private message Visit poster's website
thnk2wn



Joined: 22 Apr 2008
Posts: 31

PostPosted: Mon Apr 28, 2008 2:23 am    Post subject: Reply with quote

Thanks, that appeared to do it.
Back to top
View user's profile Send private message
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