Welcome Guest Search | Active Topics | Sign In | Register

Hierarchical Drag&Drop & Save to DB with parentID Options
Posted: Wednesday, January 28, 2009 12:19:50 PM
Rank: Newbie
Groups: Member

Joined: 1/28/2009
Posts: 1
Hello,

I'm interrested in your TreeView product, but I'd like to know if the following scenario is possible with built-in functionality or if examples are available:

I have a hierachical table using self-referencing (ParentID). I'm also using a SortOrder field for the ordering of the elements. I'd like to be able to re-order items using drag&drop, and also drag&drop items or trees to different parents.

Question is how to update the Database ParentID & SortOrder.

Thanks,

Michael
eo_support
Posted: Wednesday, January 28, 2009 1:37:00 PM
Rank: Administration
Groups: Administration

Joined: 5/27/2007
Posts: 24,194
Hi,

This involves several steps:

1. Store ID and SortOrder in each TreeNode

The first step is to store the ID and SortOrder in each TreeNode. This way as soon as you have a TreeNode object, you will know the corresponding record ID in your DB. The TreeNode object provides an extra "Value" property for you store any values. In your case, if you would like to store two values, you can devise some sort of scheme to combine two values as one, for example, using a single string value "1,5" to represent "ID is 1, SortOrder is 5". You can either use a DataBinding object to map any data field value into the Value property, or set it with code inside your ItemDataBound handler. This page contains more information about how to map a DB field to a property:

http://doc.essentialobjects.com/ViewDoc.aspx?book=1&t=MenuCommon%2fDataBinding%2fpopulate_table.html

If you use this approach, you will need to combine the two values within your SQL statement to produce a single calculated field. You can then use the following code to extract ID or SortOrder from a TreeNode at runtime:

Code: C#
private int GetNodeID(EO.Web.TreeNode node)
{
    //This code assume you use integer record ID
    return int.Parse(node.Value.Split(',')[0]);
} 

private float GetSortOrder(EO.Web.TreeNode node)
{
    //This code assumes you use a float value for sort order
    return float.Parse(node.Value.Split(',')[1]);
}


2. Update parent ID

The second step is to handle ItemMoved event. The event handler passes you the Node object as well as it's old parent Node object. It is very easy to check whether a node's parent node has been changed by comparing the old parent Node's ID with the new one:

Code: C#
protected void TreeView1_NodeMoved(
    object sender, EO.Web.TreeNodeMovedEventArgs e)
{
    int newParentID= GetNodeID(e.Node.ParentNode);
    if (newParentID != GetNodeID(e.OldParent))
    {
        //Need to update this node's parent ID
        UpdateParentID(GetNodeID(e.Node), newParentID);
    }

    //Continue to update sort order
    UpdateSortOrder(e.Node);
}

private void UpdateParentID(int id, int parentId)
{
    //Update your database.....
    .....
}


3. Update sort order

Sort order is more complicated than parent ID because depending on how you maintain sort order, you may need to update multiple records. For example, if you use integer as sort order and you have five nodes with the following sort order:

Code:

Node:  A, B, C, D, E
Order: 1, 2, 3, 4, 5


Now if you move B to be between D and E, you will need to change at least two node's SortOrder. The following shows node's B and E's sort order has been changed:

Code:
Node:  A, C, D, B, E
Order: 1, 3, 4, 5, 6


Or you can change everybody's sort order after A:

Code:
Node:  A, C, D, B, E
Order: 1, 2, 3, 4, 5


The following sample code uses float sort order, which allows you to only modify one node. For example, the new sort order with float values can be:

Code:
Node:  A, C, D, B,   E
Order: 1, 3, 4, 4.5, 5


Note B's new sort order is 4.5. This way neither D or E's sort order needs to be changed.

You would need to calculate the new sort order based on the previous node and the next node's sort order. The following code demonstrates how to do this:

Code: C#
private void UpdateSortOrder(EO.Web.TreeNode node)
{
    int nodeId = GetNodeID(node);
    EO.Web.TreeNode parentNode = node.ParentNode;

    //Find out the previous node's sort order
    float prevNodeSortOrder = 0;
    int nodeIndex = node.Index;
    if (nodeIndex == 0)  //We are the first node
       prevNodeSortOrder = 0;
    else
    {
        //There are nodes before us, so get the previous
        //node's sort order
        EO.Web.TreeNode prevNode = parentNode.ChildNodes[nodeIndex - 1];
        prevNodeSortOrder = GetSortOrder(prevNode);
    }

    //Find out next node's sort order
    float nextNodeSortOrder = prevNodeSortOrder + 2;
    if (nodeIndex < parentNode.ChildNodes.Count - 1)
    {
        //Only get the next node's sort order if we are not
        //the last node. In the case we are the last node,
        //our new sort order is simply the previous node's
        //sort order + 1
        EO.Web.TreeNode nextNode = parentNode.ChildNodes[nodeIndex + 1];
        nextNodeSortOrder = GetSortOrder(nextNode);
    }

    //Calculate the new sort order
    float newSortOrder = (prevNodeSortOrder + nextNodeSortOrder) / 2;

    //Update your database....
    UpdateSortOrder(nodeId, newSortOrder);
}

private void UpdateSortOrder(int nodeId, float newSortOrder)
{
    //Update your DB
}


Obviously you may want to change this scheme depending on how you actually store the sort order in your DB. But the basic idea should be the same.

Hope this helps.

Thanks

Matt
Posted: Thursday, January 29, 2009 10:25:26 AM
Rank: Newbie
Groups: Member

Joined: 1/29/2009
Posts: 4
This functionality is exactly what I need but when I working the issue with the trial version I downloaded my tvEMP_ORG_NodeMoved is not firiring. Am I missing something?

Code:
<eo:TreeView ID="tvEMP_ORG" runat="server"
Height="250px" Width="342px" AutoSelect="ItemClick"
AllowDragDrop="True" OnItemMoved="tvEMP_ORG_NodeMoved" >
<LookNodes>
<eo:TreeNode ItemID="_Default">
</eo:TreeNode>
</LookNodes>
</eo:TreeView>
CS:
protected void tvEMP_ORG_NodeMoved(object sender, EO.Web.TreeNodeMovedEventArgs e)
{
int newParentID = Convert.ToInt32(e.Node.ParentNode);
if (newParentID != Convert.ToInt32(e.OldParent))
{
//Need to update this node's parent ID
UpdateParentID(Convert.ToInt32(e.Node), Convert.ToInt32(newParentID));
}

//Continue to update sort order
//UpdateSortOrder(e.Node);
}

It is populating correctly (I'm using a loop and .Add(NewNode) for now)
But when a drag and drop occurs I can't get this or anyother event to fire. Please advise.

Thanks
Matt
eo_support
Posted: Thursday, January 29, 2009 10:31:40 AM
Rank: Administration
Groups: Administration

Joined: 5/27/2007
Posts: 24,194
Hi,

NodeMoved is not fired right after you moved the node. It is fired after the page is posted back. So it is possible for user to do multiple drag and drops, then post back the page, then all of them to be fired one after another.

We are posting a new build with a full working sample for this scenario. Hopefully it will be online this afternoon, you can download that sample and take a look of the source code by then.

Thanks!


You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.