I tried to built a treeview. I use MVC3.
Here is Code of mu Model
public class TreeModel : List<TreeItemModel>, IHierarchicalEnumerable
{
public TreeModel()
{
}
public TreeModel(IEnumerable<TreeItemModel> libraryTreeItemModels)
{
if (libraryTreeItemModels == null)
{
throw new ArgumentNullException("libraryTreeItemModels");
}
AddRange(libraryTreeItemModels);
}
public IHierarchyData GetHierarchyData(object enumeratedItem)
{
return enumeratedItem as IHierarchyData;
}
}
public class TreeItemModel : IHierarchyData
{
public decimal Id { get; set; }
public String Name { get; set; }
public decimal? ParentId { get; set; }
private readonly TreeModel _TreeModel;
public TreeItemModel(TreeModel treeModel)
{
_TreeModel = treeModel;
}
public IHierarchicalEnumerable GetChildren()
{
IEnumerable<TreeItemModel> treeItemModels = _TreeModel.Where(ltm => ltm.ParentId == Id);
TreeModel treeModel = new TreeModel(treeItemModels);
return treeModel;
}
public IHierarchyData GetParent()
{
if (ParentId == null)
{
return null;
}
return _TreeModel.First(tm => tm.Id == ParentId);
}
public bool HasChildren
{
get { return _TreeModel.Any(tm => tm.ParentId == Id); }
}
public string Path
{
get
{
TreeItemModel treeItemModel = (TreeItemModel) GetParent();
string path = Id.ToString();
while (treeItemModel != null)
{
path = String.Format("{0}/{1}", treeItemModel.Id, path);
treeItemModel = (TreeItemModel)treeItemModel.GetParent();
}
return path;
}
}
public object Item
{
get { return this; }
}
public string Type
{
get { return typeof(TreeItemModel).ToString(); }
}
And in TreePartial
@using System.Web.UI.WebControls
@Html.DevExpress().TreeView(
settings =>
{
settings.Name = "treeView";
settings.Width = Unit.Percentage(50);
settings.EnableHotTrack = true;
settings.EnableAnimation = true;
settings.ShowTreeLines = true;
settings.TextField = "Name";
settings.AllowSelectNode = true;
settings.ClientSideEvents.NodeClick = "function(s, e) { UPanel.PerformCallback(); }";
}).Bind(RoleTreeController.GetModel()).GetHtml()
In Controller
public static TreeModel GetModel()
{
var treeModel = new TreeModel();
var treeItemModelx = new TreeItemModel(treeModel)
{
Id = 1,
Name = "Root folder",
ParentId = null
};
treeModel.Add(treeItemModelx);
var treeItemModel2 = new TreeItemModel(treeModel)
{
Id = 11,
Name = "Folder1",
ParentId = 1
};
treeModel.Add(treeItemModel2);
return treeModel;
}
When I build, this tree is sth like this
Root Folder
- Folder 1
Folder 1 (I think this node is duplicate)
What is my wrong?
Hello Phung,
Thanks for your message. I am afraid this might take some additional time to research the problem.
We will update this thread once we have any results. Please pardon any delay that may arise.
Thanks,
Marion
P.S. You seem to be using an older build of our components (according to the report's Version field). Please visit our version info page at http://www.devexpress.com/Support/Versions.xml to learn about the most recent versions of our products and obtain instructions on how to update them.
Hi Phung,
This issue is caused by the fact that your IHierarchicalEnumerable is not well-formed. In a hierarchical enumerable, each IHierarchyData must contain its own IHierarchicalEnumerable collection of child elements. In your case all the items share one collection. Thus, the following situation occurs: the control iterates through top-level items (a treeModel instance) and finds two items: 1)Root folder and 2)Folder1. As both of them belong to the treeModel collection, they are both treated as root items.
Then, the control starts iterating in depth. For the "Root folder" item, the IHierarchyData.GetChildren() method returns the "Folder 1" item again. That is why the duplication occurs. You need to redesign your IHierarchicalEnumerable implementation.
Don't hesitate to ask me any additional questions in case of further difficulties.
With best regards,
Ivan N.
Hi Ivan,
Thanks for your help. So, How should I fix this issue?
And when user click a node (NodeClick), How can I catch it. I mind how can I catch this node ID and send it to Controller
Thanks
Hi Pnung,
You need to redesign your IHierarchicalEnumerable in the following manner:
public class TreeModel : List<TreeItemModel>, IHierarchicalEnumerable { public TreeModel() { } public TreeModel(IEnumerable<TreeItemModel> libraryTreeItemModels) { if(libraryTreeItemModels == null) { throw new ArgumentNullException("libraryTreeItemModels"); } AddRange(libraryTreeItemModels); } public IHierarchyData GetHierarchyData(object enumeratedItem) { return enumeratedItem as IHierarchyData; } } public class TreeItemModel : IHierarchyData { public decimal Id { get; set; } public String Name { get; set; } public TreeItemModel Parent { get; protected set; } public TreeModel Children { get; protected set; } public TreeItemModel(TreeItemModel parent) { Parent = parent; if(Parent != null) Parent.Children.Add(this); Children = new TreeModel(); } public IHierarchicalEnumerable GetChildren() { return Children; } public IHierarchyData GetParent() { return Parent; } public bool HasChildren { get { return Children.Count > 0; } } public string Path { get { TreeItemModel treeItemModel = (TreeItemModel)GetParent(); string path = Id.ToString(); while(treeItemModel != null) { path = String.Format("{0}/{1}", treeItemModel.Id, path); treeItemModel = (TreeItemModel)treeItemModel.GetParent(); } return path; } } public object Item { get { return this; } } public string Type { get { return typeof(TreeItemModel).ToString(); } } } public static TreeModel GetModel() { var treeModel = new TreeModel(); var treeItemModelx = new TreeItemModel(null) { Id = 1, Name = "Root folder" }; var treeItemModel2 = new TreeItemModel(treeItemModelx) { Id = 11, Name = "Folder1" }; treeModel.Add(treeItemModelx); return treeModel; }
To pass a selected node to the controller, you can handle the ASPxClientTreeView.NodeClick Event and then synchronize the selected node Id with the controller on the server side using the hidden input value. This approach is shown in detail in the following example: TreeView - How to restore the checked state when submitting a form.
With best regards,
Ivan N.
Hi Ivan,
Tree is good, but I think you don't understand one point. In this case, I have a TreeView in left handside and a UpdatePanel in righ handside (both of them in Index). Tree in left is good.
When I click to a node in tree(Root or node are ok right, all of them have a Id), I'll callback to UpdatePanel
@Html.DevExpress().TreeView(
settings =>
{
…
settings.ClientSideEvents.NodeClick = "function(s, e) { UpdatePanel1.PerformCallback(); }";
}
In UpdatePanel1:
@Html.DevExpress().CallbackPanel(
settings =>
{
…
settings.ClientSideEvents.BeginCallback = "function(s, e) { e.customArgs['NodeID'] = ??? }";
}
I want to get Id of this node I clicked and parse it to Controller by variable NodeID, so in Controller I can catch this ID.
I used Firebug to find out how to get this Id but no luck. I found many exam but almost of them are about checked node, not noteclick.
Can you show me how to get it. Javascript is not my strong point so I hard to find it out.
Thanks you.
Hello Phung,
Please accept our apologies for the delayed response. I see that you have resolved the issue related to "duplicate nodes". In order to better serve you and track multiple questions from your inquiry, we have taken the liberty of separating the issues you addressed. For quick and efficient responses to your concerns, we kindly request that future inquiries address one issue at a time.
>>I want to get Id of this node I clicked and parse it to Controller by variable NodeID, so in Controller I can catch this ID.
For now, I have created a separate ticket on your behalf:
Q280259 - TreeView - How to pass a checked Node ID to a Controller
There we will discuss this issue.
I will answer you soon. Your time and cooperation are appreciated.
Regards,
Mike