To All,
I have a requirement to create new, fully populated, nodes as leafs in a populated WebDataTree. Right now, I create a new node in CSOM JavaScript with:
var tree = $find("<%= wt.ClientID %>");
var node = tree.createNode('New Folder');
var parent = tree.get_selectedNodes();
location = $adrutil.getLocationFromDomElement(parent[0].get_element());
And, add it to the selected node (which will be the Parent Node)) with the WebDataTree add method
tree.add(node, location);
The add method then triggers the NodeAdded server side event.
My problem is that the client side Node object does not seem to have a Key property and the ParentNode property is not populated. I need to be able to create database records supporting the WebDataTree and use the generated Unique GUIDs for the new node's Key property. I thought I could set these in the NodeAdded server side event, but the e.Nodes[0] object passed is not added to the WebDataTree and seems completely detached. Executing a Nodes.Add method passing e.Nodes[0] causes another NodeAdded event to be fired.
I guess my main questing is how can I use CSOM to either build a fully developed node and add it to the selected parent node (thus, I can grab the properties and create the new database record) or trigger the server side NodeAdded method to add the fully developed node. Right now, a CSOM node is generated without a Key property and not database attached and a well formed node is created and added to the tree server side. I have duplicates.
I think I can clarify this post...
It is actually similar to the preceding post ( 'Programmatically binding WebDataTree to IEnumerable, then setting TextField and ValueField' )
What I am seeking is a means of adding a new node to an existing WebDataTree. This can be accomplished either via the client side or the server side. It makes no difference to me, but I need both the client side and the server side to be in sync.
Currently, when I create a new node and add it to an existing node as a child there is no Key property. There is only a location property. The adding of the node client side does fire the server side NodeAdded event, but the e.Node[0] object passed in the 'e' parameter is functionally empty. That is, it does contain the Text property generated client side, but contains no Key value (obviously) and no ParentNode. Additionally, no CSOM documentation that I have found demonstrates setting the new nodes Key and ParentNode properties. Regardless, when I trap the server side NodeAdded event I can create a database record and generate a valid GUID.
In the end, I need the client side node Key to be that GUID and the server side node key to be the same GUID. That way, the customer can start using that node immediately in my application or can start building more child nodes off it while keeping my database in sync with the front end.
Hello,
I am still looking into and I want to investigate further, but in the meantime I do have a suggestion if you are using an update panel like so:
<asp:UpdatePanel runat="server">
<ContentTemplate>
<ig:WebDataTree ID="WebDataTree2" runat="server" Height="300px" Width="200px" OnNodeAdded="WebDataTree1_NodeAdded" SelectionType="Single" AutoPostBackFlags-NodeAdded="On">
</ig:WebDataTree>
</ContentTemplate>
</asp:UpdatePanel>
You should be able to just grab the current selected node update the data source accordingly:
protected void WebDataTree1_NodeAdded(object sender, DataTreeNodeRangeEventArgs e)
{
//cache selected node:
var selected = this.WebDataTree2.SelectedNodes[0];
//Insert node as child of selected.Key and with e.Nodes[0].Text
this.WebDataTree1.DataSource = ds;
this.WebDataTree1.DataBind();
//optionally refresh selection:
selected = this.WebDataTree1.Nodes.FindNodeByKey(selected.Key);
selected.Selected = true;
}
This will make sure the new node gets added with its correct GUID and the tree also refreshes to match and new nodes can be assigned safely from there on.
I will update you as soon as I have something more to share, but it would be also be helpful for reproducing the behavior if you can provide any more details about the setup (update panels, postback settings and so on) or even better a small sample.
Regards,
Damyan Petev
Associate Software Developer
Infragistics, Inc.
Damyan,
I implemented your solution and it seems to work well. I have an issue with the following section:
Basically, the null is returned from this.WebADataTree1.Nodes.FindNodeByKey(selected.Key)
I think this is because the FindNodeByKey does not traverse the entire tree seeking the provided Key. Therefore, I used a homegrown function based on AllNodes. The last issue I have is that Selecting the node does not make it visible. When I rebind the tree the whole tree collapses to the root node. The application is functional. I am able to sync the database with the interface, but the interface is a bit of a kludge.
Thanks for the help. Can you look into a solution to keep the selected node active and selected after the DataBinding...
Hello Roger,
I think this post might be the solution for you if you do get to the right node:
http://ko.infragistics.com/community/forums/t/38849.aspx
Also interested in the way you get there (if you want to share) and see if we can improve on that as well.
Thanks for the guidance. Between your posts and the link I found a very good solution and figured out a bit more on how the WebDataTree control functions. Your link pointed to the DataBinding event - which I think will soon prove useful. Doing some research, I found that the Nodes returned in AllNodes inside DataBinding are populated with their Parent Nodes. I think I can adjust my system to batch update (or single update if I force a postback) and quickly sync the database and the page. But, I may have found a very intuitive solution for single node creation based on your discussion. You wanted a bit of sharing so here it is - based on the NodeAdded server side event (which I trigger by adding a node client side):
-----------------------------------------------
Protected void wt_NodeAdded(object sender, Infragistics.Web.UI.NavigationControls.DataTreeNodeRangeEventArgs e){
// An empty Key property within e.Nodes[0] object (Only processing one node at a time) is a new node...if (String.IsNullOrEmpty(e.Nodes[0].Key)) {
//Creating and adding a new nodeWebDataTree wt = (WebDataTree)sender; // Store the tree into a WebDataTree objectDataTreeNode parentNode = wt.SelectedNodes[0]; // The Selected Node (single selection) is the parentbusTreeNodeObj newNode = new busTreeNodeObj(); // Full system node object
if (newNode.CreateNewNode(Guid.NewGuid(), new Guid(parentNode.Key))){
newNode.DataRow["nav_node_isarchived"] = false; // Default to Active (not Archived) node...newNode.DataRow["nav_node_name"] = e.Nodes[0].Text; // e.Nodes[0].Text is the user defined Text nameif (newNode.NodeSave()) // Save node information to database{
//Load the tree from data storageArmory.Rules.displayArchved = IsViewingArchived();LoadWebBar(Armory.Rules.GetNavigators(Armory.Rules.GetConnectionString())); // Rebind WebDataTree
// Refresh selection and present to customer. Search .AllNodes for parent nodeDataTreeNode selected = TreeHierarchy.TreeViewUtil.FindNodeInTree(wt, parentNode.Key);if (selected != null){
selected.Expanded = true; // Expand parent/selected nodeselected.ExpandAnscestors(); // Ensure parent/selected node ancestors are expanded as well
The above is not fully debugged and tested, but between setting the NodeAdded in AutoPostBackFlags for ajax, the concept of Rebinding inside the NodeAdded server event, and the .Expanded and .ExpandAncestors() property/method I have a very clean and fast solution.
Many thanks...