Can someone describe the nested set model from a C#/LINQ perspective? - c#

I know the nested set model doesn't pertain to the C# language or LINQ directly... it's what I'm using to develop my web app.
For hierarchical data (categories with sub-categories in my case), I'm currently using something similar to the Adjacency List model. At the moment, I've only got 2 levels of categories, but I'd like to take it further and allow for n levels of categories using the nested set model.
I'm not quite clear on how to use it in a C# context. Here's the article I'm reading on the nested set model. Though this article cleared up my confusion some, I still have a big ?? in my head:
- Is inserting, updating or deleting categories tedious? It looks like the left and right numbers would require re-numbering... what would the LINQ queries look like for the following scenarios?
Delete a child node (re-number all
node's left/right values)
Delete a parent node (what do you do
with the orphans?)
Move a child node to a different
parent node (renumber again)
If my understanding is correct, at all times the child node's left/right values will always be between the parent node's left/right values, am I correct?
Seems easy enough, if only the categories were static... most likely I need to spend more time to get my head around the concept.
Any help is greatly appreciated!

Related

Is it possible to implement the opposite function of FindAncestor in XAML?

When handling the DataGrid, in code-behind I can walk downwards the visual tree, to cells and their descendants.
In XAML, FindAncestor lets us walk up the visual tree to access a target element that has no Name.
As there is no FindDescendant, I wanted to figure out how to walk downwards, not in code-behind or by MVVM.
No, at least at the moment, such FindDescendant feature is not here. And the main problem you may face trying to implement it by XAML-only is the fact there could be zero or more results matching your criteria, unlike walking the tree up where you see only one parent (or no parent at all for the root element). So the result is a collection, not a single element.
Another aspect of the problem is an ability to alter children representation by template selectors: that way, a parent node should be aware of all alterations down the tree, all the way down (maybe, zillions of levels). However, from system design point, it's better to hide such knowledge and delegate it to children nodes themselves.
Not last and not least: if you alter a parent depending on a child behavior, it may cause a circular dependency/lock if in turn the child is instructed to track the parent behavior via FindAncestor. XAML deadlocks? Thank you but no, thank you!
So, all after all, it could be very arguable ability.

ASP.net: More than 2 Nested Repeaters

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.

Pattern / Methodology For Dynamic ContextMenu Based on Collection of Objects

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

Best way to bind node collection to itemscontrol in Silverilght

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.

Slow treeview in C#

I have a legacy application that is written in C# and it displays a very complex treeview with 10 to 20 thousand elements.
In the past I encountered a similar problem (but in C++) that i solved with the OWNERDATA capability offered by the Win32 API.
Is there a similar mechanism in C#?
EDIT: The plan is to optimize the creation time as well as browsing time. The method available through Win32 API is excellent in both of these cases as it reduce initialization time to nothing and the number of requests for elements are limited to only the ones visible at any one time.
Joshl: We are actually doing exactly what you suggest already, but we still need more efficiency.
One technique for improving performance is to load TreeNodes as the user expands the treeview. Normally a user will not require 20,000 nodes to be open on their screen at once. Only load the level that the user needs to see, along with whatever child information you need to properly display affordances to the user (expand icon if children exist, counts, icons, etc). As the user expands nodes, load children just in time.
Helpful hint from Keith: With the winforms TreeView you need to have at least one child node or it won't show the expand [+], but then you handle the TreeNodeExpanded event to remove that dummy node and populate the children.
In our main WinForm app, we have a treeview loaded all in one shot:
BeginUpdate()
Load 20.000 nodes
EndUpdate()
and so far the performance is still nice. It is actually one of the few components we are not replacing with third party ones.
The TreeView performance, in my experience, gets slow when you load nodes (in one shot, or on demand) without calling Begin/EndUpdate(), especially if your nodes are sorted, but if you call Begin/EndUpdate() correctly, you shouldn't really get performance issues related to the component itself.
I don't believe the .NET TreeView supports what you want, although this type of model is supported by .NET's DataGridView (see DataGridView's VirtualMode property). The TreeView will let you draw your own nodes but it won't let you populate them from some virtual store.
If possible, you might want to consider the use of a DataGridView for your application. If not, managing the nodes manually (like joshl mentions above) might work if you can get around some issues with refreshing the screen properly when nodes are expanded. Outside of that, you might want to check out some of the third party vendors, like this one (Divelements SandGrid), that might (emphasis on might) support your desired mode of operation.
NOTE: The SandGrid is not supported by Divelements as of the end of July 2013.
NOTE: This answer is invalidated by an edit by the questioner saying he already does this kind of thing, but I decided to still post it for future reference by others searching on this topic
When I've done similar things in the past, I've tended to opt for the naive lazy-loading style.
Use the TreeNode.Tag property to hold a reference that you can use to look-up the children
Use the TreeView.BeforeExpand event to populate the child nodes
Optionally use the TreeView.AfterCollapse event to remove them.
To get the [+]/[-] boxes to appear, the best way I've found is to create a singleton dummy TreeNode that gets added as a child to all unpopulated Nodes, and you check for its existence before populating with BeforeExpand.
There is one way to make the TreeView perform much better and that is to create all sub-nodes and hook them together and then add the nodes to the TreeView. If it's the graphical performance we are talking about.
TreeView tree = new TreeView();
TreeNode root = new TreeNode("Root");
PopulateRootNode(root); // Get all your data
tree.Nodes.Add(root);
Otherwise, load them node by node using OnTreeNodeExpanded.
For large data in Windows C# programming, whether it be in WPF or WinForms, I have traditionally added nodes dynamically. I load the initial tree root + children + grandchildren deep. When any node is expanded, I load the tree nodes that would represent the grandchildren of the expanding node, if any.
This pattern also works well with data retrieval. If you are truly loading data from a source of thousands or millions of records you probably don't want to load those all up front. No user wants to wait for that to be loaded, and there is not reason to load data that may never be viewed.
I have typically loaded the grandchildren or the great-grandchildren node data as needed on a background thread, then marshal those data back to the UI thread and create and add the nodes. This leaves the UI responsive. You can visually decorate tree nodes to indicate they are still loading for the case where a user gets ahead of your IO to the data store.
This works for me (CSharp):
Visible = false;
...
Visible = true;
In my case(2000 nodes), it takes only 1~2 seconds to load the tree, which is much more quicker than any other ways.
It might work well in C++.

Categories