Page 1 of 1

How to programmatically ensure the visibility of TreeView's item

Posted: 12 Mar 2018, 06:15
by satorp
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.

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

Posted: 12 Mar 2018, 19:16
by sfernandez
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();

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

Posted: 13 Mar 2018, 08:26
by satorp
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.

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

Posted: 13 Mar 2018, 13:13
by sfernandez
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.

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

Posted: 13 Mar 2018, 13:33
by sfernandez
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.

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

Posted: 14 Mar 2018, 09:01
by satorp
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.

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

Posted: 14 Mar 2018, 11:47
by sfernandez
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.

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

Posted: 14 Mar 2018, 13:27
by satorp
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.

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

Posted: 14 Mar 2018, 18:35
by sfernandez
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.

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

Posted: 15 Mar 2018, 09:49
by satorp
Thank you. We will also consider that option.