Ticket Q353979
Visible to All Users

TreeView - How to avoid duplicate nodes

created 13 years ago

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?

Show previous comments (3)
DevExpress Support Team 13 years ago

    Hi Pnung,
    You need to redesign your IHierarchicalEnumerable in the following manner:

    C#
    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

        Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

        Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.