Limit how deep TreeView would go when expanding TreeNode in WPF - c#

I'm using WPF TreeView bound to my classes though MVVM to display a large array of multilevel data. Because of this, when I expand TreeNode, it takes some time and a lot of memory.
I think, that the memory requirement comes from TreeView scouting out nodes down the line, not just the first generation of the children, forcing those nodes to load data.
Is there any way to limit this "scouting" behavior to only the first generation of child nodes?

WPF generates TreeViewItem(s) only when they are displayed, i.e. no item is generated until its Parent expanded. So, I think the problem is not a "scouting".
Anyway, you may try to implement dynamic loading in your ViewModel by adding synchronization with TreeViewItem.IsExpanded using TwoWay Binding. Take a look at this. You may use the same solution for IsExpanded property. Don't forget to add fake item to tell TreeViewItem that it is expandable.

Check if TreeView is using VirtualizingStackPanel. I believe that it is used by default in .NET 4.0, but you must set it explicitly in previous .NET versions.
For more information, see How to: Improve the Performance of a TreeView.

Related

Reusing visual tree when moving items between two ItemControls

I have two ObservableCollections in my ViewModel. Both of same generic type.
Window has two ItemsControls each with ItemsSource bound on its own ObservableCollection from ViewModel.
Both use same same ItemTemplate. This ItemTemplate is very complex user control.
It's all done by the book.
In some cases, I move item from one collection to another. UI updates correctly. However, as control is complex, it needs about 1-2sec to render when it is recreated in new ItemsControl. And since this happens on drag and drop operation, it is not user friendly.
What I would like to do is to somehow preserve existing instance of ItemTemplate from source ItemsControl and reuse it in destination. I don't know if it is even possible, I couldn't find anything about it online.
I believe setup is fairly simple, but if needed I'll write some simplified version of code (I can't share the real code).
Thanks for any help.
What I would like to do is to somehow preserve existing instance of ItemTemplate from source ItemsControl and reuse it in destination. I don't know if it is even possible, I couldn't find anything about it online.
I am afraid it is not. When you disconnect an element from the visual tree and then add it back to a different parent element at a later stage, all elements that make up the control will be re-rendered.

HierarchicalDataTemplate - Ignore specific types on generation

My problem is the following: I got a Tree which has an dynamic depth of categories (each category can have sub-categories as well as entries).
Now I added a HierarchicalDataTemplate for the categories to display correctly in the TreeView. But I get a lot of empty entries, which do not apply the Template (wrong type) but show up in the tree as 'corpse'.
How can I ban them from the generation process? Because it's an abstract tree, they are of the same base-class as the categories are. So they get into the tree, because the tree always searches the "Branches"-property which contains either categories, entries or both.
Any ideas? I didn't find any event of the TreeView which probably give me the opportunity to skip various entries during generation nor any option/property of the template to do so.
Detailed Description: I got a generic Tree class. This class has branches of type "A_TreeLeaf" (abstract). The Tree's generic type must inherit A_TreeLeaf of course. My data is structured in categories (CategoryTreeLeaf) and Data (DataTreeLeaf). Each leaf can have sub-leaves (branches), of course.
Now I load my data from a database and build the tree. Each category has X sub-categories. And each category also could contain some Data. This structure helps me a lot, because I got an clear hierarchic structure of categories and data. This way it should be visualized to the user. But I want to separate Data and Categories. The TreeView should show just the categories (by an HierarchicalDataTemplate) and the ListView just the Data (by an DataTemplate). The ListView works fine, but the Tree shows some "corpse"-entries which are the DataTreeLeaf-instances.
I want to filter the DataTreeLeafs on generation or just stop the TreeView displaying them. Is there any "non-hack" solution? I don't want to copy the tree and remove the Data-leaves unless it's really necessary... because this would cause a lot of overhead work to do for me and to manage either the code behind which uses the real tree or the visualization with the fake-tree (because I need to bridge it somehow that it's updated automatically when one of both changes).
You have a unique problem... you have some data items in your hierarchical data that you don't want to display, but for some reason can't remove. If that sums up your problem, then you're doing something wrong.
In WPF, you shouldn't need to hide data items from the UI, instead you simply don't put them into the collection in the first place. It sounds like your process of filling your hierarchical data is flawed and you'd be better off fixing that at the source than trying to deal with the problems that it causes in the UI.
If you can't fix the actual process for whatever reason, then your next best option is to iterate through the data before you display it and simply remove any data elements that shouldn't be there. When using WPF, it is always best to provide your UI with data that fits the purpose.
However, if for whatever reason you can't even do that, then your last option is to simply define an additional DataTemplate for your abstract base class and just leave it empty:
<DataTemplate DataType="{x:Type YourDataTypesPrefix:YourBaseClass}">
</DataTemplate>
Of course, you'd have to define DataTemplates for each sub type, or they'd also be rendered empty.

Updating treeview control in WPF

In my application as soon as an object is dropped on canvas I stored it in a tree. Now, I'm trying to write a method to delete an object which is fine but I also need to delete that specific object from the tree. Each object has a unique id so this way I can find it in tree and remove it from tree while being deleted from the canvas.
In order to find a node in tree I have planned to store ID in each node (item.Tag), however, I'm facing two problems:
How can I access to details of a node from a different class? myTreeObj.Items.Tag doesn't work properly.
When I loop in tree myTreeObj.Items.Count shows more items that what I see.
Any comments will be appreciated.
Thanks.
In WPF, TreeViews are actually what they say they are: a view of a data structure. In WinForms, you had to crawl up and down the nodes of a TreeView and add them or remove them manually. In WPF, the proper approach is to add or remove items from the actual data hierarchy (to which the TreeView is binding) and use PropertyChanged or CollectionChanged notifications to tell the TreeView to update itself automatically.
What you are trying to do may be possible, but it is going to be an uphill fight all the way, and things will not work as expected. WPF REALLY wants you to use databinding, and any other approach is going to give you headaches.
This article may be a helpful place to start understanding how to work with the WPF TreeView:
http://joshsmithonwpf.wordpress.com/2008/05/24/the-wpf-treeview-is-a-view-of-a-tree/
EDIT:
The author's original article is actually more helpful:
http://www.codeproject.com/Articles/26288/Simplifying-the-WPF-TreeView-by-Using-the-ViewMode

Better than TreeView

I'm binding a lot of data to a TreeView control as the data is a natural category hierarchy. The problem is that there is a lot of it. I have managed to remove a lot of the overhead by only binding those nodes which appear in the visible tree, but this still leaves a lot in the ViewState, et al.
Does anyone have a method or alternative control for improving this kind of performance issue, please?
I was thinking about trying to inherit the TreeView control and dump it's viewstate value into Sesssion and back - but it's quite a hack I don't really have time for, right now...
Yes ... you can use On-demand Loading or Lazy loading of Tree View Items
i.e.
1- Only show root level nodes as in the Window Explorer.
2- when user Clicks a node , than only fetch the child nodes and show.
in this way , you will see only those nodes which actually user requested.
and you can give a checbox , which say 'SHOW WHOLE TREE EXPANDED' obviously , it would take more time to show.
you can also implement Node search functionality but please remember tree is specilized form a graph so use proper grpah algorithm while finding a node like (BFS or DFS)
you can also cache the results of nodes but this should be only done in the case when your tree itself is not used for hierarchy updation.
apart from the solution of dynamically loading tree view on expand, try ViewStateCompression for viewstate enhancement, use Asp.net Caching for output caching or just cache the objects by dynamically adding objects to cache using generating keys like "tree_" & parent. Cache objects are shared between sessions, so it will even be more helpful.
Hope this will help.

How is the Parent property of a FrameworkElement set in Silverlight?

I have written a custom Silverlight control based on Control. I have two DependencyProperties called Top and Bottom which both hold child controls for a specific layout display. I then use a ControlTemplate to arrange these two controls into a grid, placing one on the 0 row and the other on the 1 row. The problem I have is that I cannot seem to figure out how to get each child control's Parent property to point to my custom control. When I inspect each control at run-time, the Parent property of each is null.
This is a simple example, but I think you can see the general problem. I have a number of more complex controls that all share this problem. I know there is some magic I am missing. If a ContentControl's Content property is set to some child it is somehow setting that child's parent to itself.
Edit: A little more info
In WPF, one might use functions like AddVisualChild(), RemoveVisualChild(), AddLogicalChild(), RemoveLogicChild() to manage parent/child relationships, but these functions are not available in Silverlight.
After quite a bit of research I believe that this is not possible. I was able to recurse through the Visual Tree instead of the Logic Tree using the VisualTreeHelper to accomplish my ultimate goal.
The Parent property cannot be arbitrary, it reflects the real parent of the control for use when rendering.
From MSDN:
Parent may be a null reference (Nothing in Visual Basic) in cases where an element was instantiated, but is not attached to any logical tree that eventually connects to the page level root element, or the application object.
...
Changing an element's parent is typically only done through manipulation of collections, by using dedicated add or remove methods, or through setting content properties of elements.

Categories

Resources