satorp
Topic Author
Posts: 5
Joined: 12 Mar 2018, 05:48

How to programmatically ensure the visibility of TreeView's item

12 Mar 2018, 06:15

Hi,

Is there a way to programatically scroll to a TreeView's item so that it's visible?
I've tried using
ItemsControl::BringIntoView(BaseComponent* item)
but it doesn't seem to work if the TreeView items are generated by hierarchical templates.
Note that WPF's TreeView implements its own BringIntoView which seems to be missing in Noesis GUI.
 
User avatar
sfernandez
Site Admin
Posts: 1911
Joined: 22 Dec 2011, 19:20

Re: How to programmatically ensure the visibility of TreeView's item

12 Mar 2018, 19:16

Hi,

Are you sure WPF's TreeView implements its own version of BringIntoView, I'm not sure about that, look in their public code:
https://referencesource.microsoft.com/# ... reeView.cs

Do you have a way to get the TreeViewItem container of the item you want to bring into view?
If that is the case you can simply call treeViewItem->BringIntoView();
 
satorp
Topic Author
Posts: 5
Joined: 12 Mar 2018, 05:48

Re: How to programmatically ensure the visibility of TreeView's item

13 Mar 2018, 08:26

I'm not sure about their actual implementation. I just guessed so because WPF TreeViewItem::BringIntoView seems to work, while in Noesis GUI, the method is unavailable in the first place (protected). Is there a reason for the FrameworkElement::BringIntoView being overridden as protected?
Casting TreeViewItem into FrameworkElement and calling FrameworkElement::BringIntoView works, but with slight differences from WPF. It only works if the item is already expanded, while in WPF it will expand and scroll to the item if it's collapsed.
Also as I stated in my previous post, for items generated using hierarchical data templates (as in my case) it seems that only containers (TreeViewItems) of the topmost items can be retrieved using ItemContainerGenerator::ContainerFromItem. Is there a way to retrieve the subtree items too?

Thank you.
 
User avatar
sfernandez
Site Admin
Posts: 1911
Joined: 22 Dec 2011, 19:20

Re: How to programmatically ensure the visibility of TreeView's item

13 Mar 2018, 13:13

I'm not sure about their actual implementation. I just guessed so because WPF TreeViewItem::BringIntoView seems to work, while in Noesis GUI, the method is unavailable in the first place (protected). Is there a reason for the FrameworkElement::BringIntoView being overridden as protected?
BringIntoView(BaseComponent* item) is an internal method of ItemsControl only available for inheritors as it occurs in WPF just with another name: OnBringItemIntoView(object arg)). It is different from the one exposed by FrameworkElement that accepts no parameter or a Rect.
but with slight differences from WPF. It only works if the item is already expanded, while in WPF it will expand and scroll to the item if it's collapsed.
This seems to be a bug. Could you please create a ticket in our bugtracker?
Also as I stated in my previous post, for items generated using hierarchical data templates (as in my case) it seems that only containers (TreeViewItems) of the topmost items can be retrieved using ItemContainerGenerator::ContainerFromItem. Is there a way to retrieve the subtree items too?
This is a problem in WPF too because of how ItemContainerGenerator is designed:
https://stackoverflow.com/questions/394 ... witem-only
https://social.msdn.microsoft.com/Forum ... erlightnet

The only way right now to do this would be to manually search for the item. But this will be a very costly process as you'll need to expand each TreeViewItem, and do a tv->UpdateLayout() before continuing looking in its children. To know if a TreeViewItem corresponds to the specified item you can compare against its Header.
 
User avatar
sfernandez
Site Admin
Posts: 1911
Joined: 22 Dec 2011, 19:20

Re: How to programmatically ensure the visibility of TreeView's item

13 Mar 2018, 13:33

Looking into this article http://alookonthecode.blogspot.com.es/2 ... n-wpf.html (see SelectItem function at the end).
The process I explained before can be speed up a lot if your data items know about their parent data items, as you can search down only the branch of TreeViews corresponding to the specified item.
 
satorp
Topic Author
Posts: 5
Joined: 12 Mar 2018, 05:48

Re: How to programmatically ensure the visibility of TreeView's item

14 Mar 2018, 09:01

Hi Sergio,
BringIntoView(BaseComponent* item) is an internal method of ItemsControl only available for inheritors as it occurs in WPF just with another name: OnBringItemIntoView(object arg)). It is different from the one exposed by FrameworkElement that accepts no parameter or a Rect.
My concern is BringIntoView() being hidden from TreeViewItem because of the protected overload in ItemsControl, so we need to cast TreeViewItem* to FrameworkElement* to call the method. In WPF the BringIntoVIew() method is visible from TreeViewItem instance. I think it's better if you can reintroduce the method on ItemsControl interface (maybe by "using" declaration).
This seems to be a bug. Could you please create a ticket in our bugtracker?
I will register the issue to your bugtracker.
The only way right now to do this would be to manually search for the item. But this will be a very costly process as you'll need to expand each TreeViewItem, and do a tv->UpdateLayout() before continuing looking in its children. To know if a TreeViewItem corresponds to the specified item you can compare against its Header.
Looking into this article http://alookonthecode.blogspot.com.es/2 ... n-wpf.html (see SelectItem function at the end).
The process I explained before can be speed up a lot if your data items know about their parent data items, as you can search down only the branch of TreeViews corresponding to the specified item.
Thank you. I've missed the fact that each TreeViewItem has their own container generator, and they need to be realized (expanded) first. Indeed our data item knows about their parent, so I've implemented the feature as you suggested, searching from topmost parent down after expansion, and it works.
 
User avatar
sfernandez
Site Admin
Posts: 1911
Joined: 22 Dec 2011, 19:20

Re: How to programmatically ensure the visibility of TreeView's item

14 Mar 2018, 11:47

My concern is BringIntoView() being hidden from TreeViewItem because of the protected overload in ItemsControl, so we need to cast TreeViewItem* to FrameworkElement* to call the method.
I understand your concern now, we should rename the internal function to avoid hiding the FrameworkElement public function.
Sorry for the misunderstanding.
 
satorp
Topic Author
Posts: 5
Joined: 12 Mar 2018, 05:48

Re: How to programmatically ensure the visibility of TreeView's item

14 Mar 2018, 13:27

By the way, I'm now working on a small project of creating a tool for visualizing Noesis GUI visual tree. Can you suggest the best way to monitor a change in visual tree (e.g. visual child added or removed)? Is there any change event I can hook to from outside the Visual class? I've tried using SubtreeDrawingCommandsChanged event, but it seems to be raised on too many occasions.
 
User avatar
sfernandez
Site Admin
Posts: 1911
Joined: 22 Dec 2011, 19:20

Re: How to programmatically ensure the visibility of TreeView's item

14 Mar 2018, 18:35

There is no generic way to detect that kind of changes in the tree.

The only way would be to detect changes in the specific properties of the container elements: Decorator.Child, ContentPresenter.Content, etc.
And Panel.Children collection provides a INotifyCollectionChanged interface that you can use to detect changes there.

Hope this helps.
 
satorp
Topic Author
Posts: 5
Joined: 12 Mar 2018, 05:48

Re: How to programmatically ensure the visibility of TreeView's item

15 Mar 2018, 09:49

Thank you. We will also consider that option.

Who is online

Users browsing this forum: sfernandez and 1 guest