Background
I have a TreeView that follows the MVVM design pattern and supports multiple selection by recording TreeViewItem selections in a List. As it stands there are several types of TreeViewItems available for the user to select.
They are:
Two Root nodes of type WorldFolder and MyDataFodler which can contain child Folder types
Child Folder nodes of types LocationFolder, PersonFolder, CollectionFolder
Child Item nodes of type LocationItem, PersonItem
CollectionFolder can contain child nodes of Folder types
In all this works very well with very little code and supports collections of Locations and People and furthermore Collections within Collections.
Problem / Question
My top level view-model keeps track of the selection state of TreeViewItems and the current selection may be a combination of Item, Folder or even Root type nodes. Depending on the user's selection I want to create a dynamic ContextMenu. So far this works! When I select several LocationItem and/or PersonItem type nodes my view-model generates a custom ContextMenu. The problem is the complexity! My view-model is quickly turning into dozens of if/else if/else statements to capture all the possible permutations!
For example:
if (_selectedItems.All(item => item is PersonItem)) // Only people selected
{
// Create ContextMenu based on only PersonItems
}
else if( _selectedItems.All(item => item is LocationItem)) // Only Locations
{
// Create ContextMenu based only on LocationItems
}
...
Is there a better way to handle all the possible permutations of user choices and generate my ContextMenus more efficiently?
* Sorry about the code formatting, it's been giving me grief all week *
I can't remember where I read this wise saying:
The best way to work with a TreeView is not not to work with the TreeView
What does this mean? Move the functionality into the tree nodes and keep the tree view as thumb as possible. Unfortunately, by default the tree node does not many events, though, it's easy to redirect the tree view events to the nodes.
Once done, you can override the ContextMenuStrip property in your nodes. The first selected node creates the list of ToolStripItems it wants to handle and asks the tree view which are allowed (e.g. with a FilterMenuItems(desiredItems) method). The tree view asks all selected nodes which of the nodes they would be able to handle. The result is your context menu.
This should work with almost any count of different nodes and keeps the tree (nodes) easy to maintain.
Edit: Dang! Missed the WPF tag, so I cannot asses the available events, since I did not yet work with WPF
Related
I have a treeview that displays a few nodes, say 5 or so. When the final node is selected, I want to display records belonging to that final node (linked via a foreign key) inside of a listbox.
So the structure would be
Treeview Listbox
-1 -Object belonging to 5
--2 -Object belonging to 5
---3
----4
-----5
My question is if such a comperation between these two controls is even possible and if I'm going about it the smartest way.
I can't find anything about it (getting actual data from the last selected node in the treeview is already pretty hard on how to find a how to). Any tips in the right direction would be very appreciated.
It is possible to do this exactly the way you're trying to by using attached properties, but it's a bit of a clumsy way of going about it. What you really should be doing is using data binding.
Your TreeView is, presumably, bound to some kind of data structure in your view model (data context), and what class that is should (again, presumably) be able to easily ascertain whether or not a particular given item is the deepest/last one in the tree. So create a property in that class and bind the TreeView's SelectedItem to that, so that it gets updated whenever the user selects an item in the Tree. Next, create another property for your ListBox to bind to. When your first property gets set, it either sets this second property to the currently selected item if it's the last in the list, or sets it to null if it isn't.
By doing this you de-couple your logic from your view and you make something that's much easier to debug, test and modify in future.
I have a TreeView which data source is generated in runtime through code to which I don't have access. Its hierarchical data, nodes of tree with 2, 3 or 4 depth levels. I have to make the same structured tree with RadioButtons corresponding to every object in first tree. Is there a way to iterate through every element of TreeView or another method to do my task?
In WPF, we use DataTemplates, or in your case HierarchicalDataTemplates to define how our data should be presented. You already have the data in the first TreeView and that should be accessible from its ItemsSource or Items properties. Therefore, all you need to do is to define another HierarchicalDataTemplate to display the same data object the way that you want it. There is no need to manually iterate through all of the nodes from the original TreeView.
I'm creating some custom object using ContentControl and by adding them to toolbox allowing user to drag/drop them on a page. Now, I'm facing a situation where some of these controls have children. In case it is only one item without children I retrieve each object's id in Tag property, however, for the 2nd category this won't be the case, since I need to store and retrieve a hierarchy set of IDs. After few searches I ran into MSDN forum and it is almost close to what I need to do but I was wondering there are better and more optimized methods of implementation.
Any help will be appreciated.
Thanks.
If an object can have more than one child you use an ItemsControl and not a ContentControl. And an ItemsControl containing ItemsControls is a hierarchy.
My data comes from a database. I have an item data table with some basic properties.
Item
{
ID,
Name,
Description,
...
}
Then I have a many to many relationship table with:
Parent
{
ParentID,
ChildID
}
I'm iterating through each item and displaying its children; and its children's children, etc. I assume this would best be accomplished with nested repeaters, but I could be wrong.
How do I get multiple heirarchical levels using asp:repeaters? I've only ever used one nested repeater, I have no idea how to do 3+.
Personally I probably do this by creating a custom control with an Item property and some sort of either Parents or Children property. The control would display details on Item, and then use a repeater to show each element in Parents / Children, where for each item the repeater recursively uses the same control to render the item.
I would do what #Kragen said. But if you really think that creating two components is too much you should use one repeater and two foreach loops in on data bound.
Using two repeaters one inside of another is overcomplicated not to mention 3 repeaters :).
A Parent-Child relationship, which is many-to-many? This doesn't make sense, at least calling them a parent and a child doesn't make sense. If it is really many-to-many, it's a network, if a child only has ONE parent, then it is a hierarchy.
With the former, I'm not sure visualizing them in that way is any good. How do you visualize a child with more than one parent?
With the latter, why not use a TreeView with a custom item template? It handles all the hierarchy stuff automatically. The problem with repeaters is that if you are not doing them dynamically (creating them in code), then the level of nesting is fixed and you cannot go as much as you want. Doing them dynamically would work, but would bring overhead.
I'm not very sure what exactly you are trying to accomplish. Maybe providing some more details about the end-result you need to see would be helpful.
I have a Silverlight project where the main objects are just a bunch of nodes that are joined to each other. A parent node can have many children.
I want to be able to bind the nodes to an itemscontrol or similar and so was wondering how to best structure the parent child relationship.
Is it OK to create a flat top level list of all nodes (List allNodes) and add each node to that, binding the list to the itemscontrol, then on top of that add each node to it's parent's 'childnodes' list to establish the structure - or am I doing some kind of ugly doubling up?
Just hoping there is some kind of best practice or pattern I can latch on to
Thanks
You should use the treeview found in the official silverlight toolkit. Here is an online demo.