Programmatically Adding a TreeViewItem - xaml

I'm trying to programmatically populate a treeview in UWP. However, I'm getting confused between TreeViewItem and TreeViewNode.
I can add a TreeViewNode to another TreeViewNode like this:
Windows.UI.Xaml.Controls.TreeViewNode node = new Windows.UI.Xaml.Controls.TreeViewNode();
node.Content = myInfo.Name;
parentNode.Children.Add(node);
However, my understanding is that when I get down to the lowest level, I need a TreeViewItem; e.g.:
root
- Level 1 - Node
- Level 2 - Node
- Level 2 - Node
- TreeViewItem?
- Level 1
- TreeViewItem?
However, I can't do this:
Windows.UI.Xaml.Controls.TreeViewItem node = new Windows.UI.Xaml.Controls.TreeViewItem();
node.Content = data;
node.Tag = tagInfo;
parentNode.Children.Add(node);
I assume that I'm misunderstanding the purpose of a TreeViewItem. Please could someone point me in the right direction?

Yeah the thing is... as you can see here the TreeViewItem is the Root of the TreeView Item Template and the TreeViewNode is the "actual" Item.
Oversimplified
IF you want to add items to your TreeView, then you HAVE to use the TreeViewNode class
IF you want to "redesign" your TreeViewNodes, lets say instead of normal hierarchical list look you want to have some hexagon list, then you have to implement the TreeViewItem in your Style/Template

Like Zer0 said, you don't have to use TreeViewItem. In fact, the basic component that makes up a TreeView is the TreeViewNode. The TreeViewItem can be thought of as a TreeViewNode container of the same level and style. It has the ItemsSource and ItemTemplate properties, which can create the same "TreeViewNode" in batches according to the data collection.
The relationship between TreeView/TreeViewItem/TreeViewNode is like the relationship of building/wall/brick. The wall is made up of many identical bricks and can itself be seen as a large brick.
Best regards.

Related

ListView containing GridViews and ListViews

I have a requirement to create a xaml page with Semantic Zoom where the zoomed in view contains both GridViews and ListViews. I have started out with the basic Grid Application template.
In order to try to achieve this, I have made the Semantic Zoom control's zoomed in view show a list view, and the list view contains the ListView and GridView controls I need to actually show the data as ListViewItems. This works, up to a point - the issue is that the mouse-down or tap animations happen on the whole child control of the parent ListView instead of the child's elements. This sort of layout would be simple if I didn't need to support semantic zoom.
So, my question is is this the best way to achieve this sort of layout, or am I missing something. If this is the best way, is it possible to control the behaviour so that the child item elements have the correct animation effect on selection?
Additional Info
The choice of GridView or ListView is based on the type of the items in the collections. In this example, grp 1, 3 and 4 (to be shown in grids) are all collections of type NewsFull and the remainder (to show in Lists) are of type HeadlineOnly, both types inherit from NewsBase.
The page layout (zoomed in) should be something like this...
Title
grp 1 grp 2 grp 3 grp 4 grp 5
[g][g][g][g] [_list item_] [g][g][g][g][g] [g][g][g] [_list_item_]
[g][g][g][g] [_list item_] [g][g][g][g][g] [g][g][g] [_list_item_]
[g][g][g][g] [_list item_] [g][g][g][g] [g][g] [_list_item_]
[g][g][g] [_list item_] [g][g][g][g] [g][g]
where [g] is a grid view item, and [_list_item_] is a list view item.
Zoomd out view is like this...
Title
grp 1 grp 2 grp 3 grp 4 grp 5
[summary] [summary] [summary] [summary] [summary]
Perhaps you can try using the ItemContainerStyleSelector to swap out the container of the items based on the item type or similar? This way, may be you can set one group to have a wrapping layout container and another can just be a stackpanel?
the design looks reasonable to me. the issue you have is merely " is it possible to control the behaviour so that the child item elements have the correct animation effect on selection?"
the problem here is that you probably lack abstraction here regarding different levels of UI object. I would assume you wrote this big control simply using one xaml object and then messed up with the style setup. In my opinion, you will need to break your UI to these levels of components:
ZoomPage // which is essentially a list
GroupElement // which could be GRID object or list object depending on the DATACONTEXT
GroupElement // which also has a summary state.
what you specified definitely can be achieved, looks to me just the styles are not deployed properly, if indeed your control is too complex, break it down, and test them separately.
hope this helps

ExtJS 4: Add children tree nodes to a non-Root node dynamically?

I am trying to add children tree nodes to a non-Root node dynamically when it's selected.
This is how I implemented it:
First, I populate my tree with a TreeStore then to dynamically add children tree nodes, I handle it on the itemexpand event in tree Controller.
//pThis is a NodeInterface obj of the selected node
itemexpand: function (pThis, pEOpts) {
//type is an attribute that I added so that I know what type of node that got selected
if (pThis.raw.type === 'Staff' && !pThis.hasChildNodes()) {
var staffNodeAry = [{text:"Teachers", type:"ChildStaff", leaf: false},
{text:"Principals", type:"ChildStaff", leaf: false}];
pThis.appendChild(staffNodeAry);
}
}
This worked quite good because I am able to see both "Teachers" and "Principals" node under "Staff" type but there are 2 issues that I found so far:
1) There's this error on the console:
Uncaught TypeError: Cannot read property 'internalId' of undefined
I don't know why but if anyone could enlighten that would be great.
2) When I expand either "Teachers" and "Principals", the NodeInterface obj that's returned by itemexpand has an undefined raw object.
So I couldn't do this: pThis.raw.type
From my understanding, I don't need to create a new TreeStore to add any new children nodes, I thought that by creating an array of objects that adhere to NodeInterface should be enough but I might be wrong.
If anyone could point me to the right direction, that would be great.
Handi
More info:
What I did was actually following the ExtJs 4 documentation so I believe this is a bug on ExtJs 4 framework.
I also tested this with Extjs-4.1.0-rc3 and it also produced the same error.
I have resolved this issue changing the event itemexpand with the event afteritemexpand. I have no documentation to justify this. The debugger says to me that the view listen for the itemexpand event and do something that goes wrong if add a node manually...
For the question number 2: you have no raw object because it is created by the reader of the store after the load operation. So if you add a node by hand the raw object does not exists.
http://docs.sencha.com/ext-js/4-1/#!/api/Ext.data.Model-property-raw
The documentation for .appendChild() functions says:
node : Ext.data.NodeInterface/Ext.data.NodeInterface[]
The node or Array of nodes to append
And you are trying to append an array of 2 objects, but they are not "NodeInterface" instances. So you should create them properly like so:
var nodeToAppend1 = pThis.createNode({text:"Teachers", type:"ChildStaff", leaf: false});
pThis.appendChild(nodeToAppend1);
I remember making the same mistake a year ago, so I hope this helps.
I think it happens because your Ext.TreePanel working asyncroniously. So add process is:
Append Child, add virtual child leaf to your tree, with red mark in corner
Call store's create api
Receive response, if it success=true, change with virtual
The goal of changing is set internakId property, so you can add new child only after this change happens. I think better is write some recursive function and bind it to store's added event
tree.getStore().on('update', addChild);
or
tree.getStore().load({
success: function() {
addChild()
});

Sencha Touch 2: Insert into TreeStore/NestedList

I'm using a NestedList with a underlying TreeStore. Now I want to add items to the NestedList as leafs.
How can I do this?
Currently my code (Controller, onAddButtonTapped) looks like this:
var store = Ext.getStore('menuStore');
var customerAreaNode = store.getRoot().getChildAt(1);
customerAreaNode.appendChild({name: "text", leaf:true});
customerAreaNode.expand();
store.sync();
This code results in two new empty listentries on leaf level (behind the correct node) and one new listentry on node level.
Every new entry has no names shown in the NestedList but every item contains "text" in their name field. Curiously one of the new entries at leaf level is not typed to the underlying Model. So the model-corresponding methods could't be found:
Uncaught TypeError: Cannot call method 'getSelectedName' of undefined
Does anybody know a easy tutorial how to add data into NestedList/TreeStore? I could not find one good example in the sencha touch docs.
The default display field for leaf items is "text". You can get the information from here. If you want to use "text" as display field, then you need to change this line to
customerAreaNode.appendChild({text: "text", leaf:true});
Or you can change your nested list's display field, so your model do not need to change for this time.
yournestedlist.setDisplayField('name');
Hope this helps.
In my case i used to update root and child nodes like the following way
Ext.getStore('Contactsstore').getAt(1).getChildAt(0).set('Email',contactemail);
Ext.getStore('Contactsstore').getAt(1).set('ContactTitle',contacttitle);

libxml - looping through all children of a child

I am new to libxml. I would like to write 1 loop to loop through all the children of a child node etc. e.g.
<par>i want to <bold>loop <italic>through </italic> all</bold> children in this node</par>
At the moment my looping code look as follows but I only get the "bold" node and not the "italic" child.
if (xmlStrEqual(node->name, BAD_CAST "p")) {
xmlNodePtr child = node->children;
while (child != NULL) {
child = child->next;
}
}
It is conceivable that the node structure could grow to 4-5 elements, so I need a solution which is more robust that putting while loops within while loops. Any help would be appreciated please.
The xmlTree interface you're using is heirarchical. <par> has 3 children - the text before <bold>, <bold> itself, and the text after. <bold> has children of its own, which includes <italic>. The node->children list only contains the immediate children of a node.
There are a couple ways to get the behavior that you want.
While processing child, you can recursively process child->children to get to <bold>'s child, which includes <italics>
If you're looking SPECIFICALLY for that <itallic> (or for a set of specific nodes), you can use an XPath expression, such as "par//italic" to find any italic node anywhere beneath par.
http://www.xmlsoft.org/examples/index.html#XPath
You could look at libxml2's xmlTextReader interface rather than this xmlTree. It provides the serial "read through" of the document that you're expecting.
http://xmlsoft.org/xmlreader.html
Each method has its own advantages/disadvantages, depending on what all you're trying to do with your application.

How to add a new node to a dijit.Tree

I want to add a new node to a dijit.ree as a sibling of the currently selected node. I've found sample code (I'm new to dojo) that adds a new item to the tree using the newItem method of ItemFileWriteStore, but the new item always appears at the bottom of the tree. How would I add to the store at a specified position, in particular the position corresponding to the current selection? Pointers to sample code would be welcome :)
Thanks,
Larry
You need to find the parent item of current selected node and use that item as the parent of the newly created item.
store.newItem(itemObj, {parent : parentItem, attribute : children});
Normally an item in the store doesn't have a back pointer points to its parent. So you may need to maintain that yourself. For example, you can store the parent item's id in the child item and use fetchItemByIdentity to get the parent item.
I figured it out; here's the answer for future searchers. Use newItem as Alex suggested. Then use model.pasteItem to reposition the new item. pasteItem takes a parent (selectedNode.item.parent[0]) and a position (selectedNode.getIndexInParent()+1)
Larry
store.newItem is giving an error (Uncaught Error: dojo.data.ItemFileReadStore: Invalid attribute argument. ). Could not really find a fix for this so far and my store does not have duplicate id's.
Hence i tried using model.newItem(newItem, parentItem).
This works perfectly alright.
Thanks,
Srilatha.