Skip to main content
Question

How to hierarchize tree views

  • November 21, 2025
  • 0 replies
  • 20 views

Hi everyone, I am having a problem in a field when I press the Data Field button, the system will take the entire view name as the parent node and the data field as the child node in the view name of the screen that I have selected to display to allow the user to select in the list. However, currently the view name and data field are on the same level without hierarchy, for example PIDetail is the view name, but warehouse is the data field. The result is returning a flat list of child nodes in the repeated parent nodes. Here I attach the capture of my problem, I really appreciate you responds and help.

Code for logic:

   public PXSelect<EntityItem> EntityItems;
        //public PXSelect<EntityItem> PreviousEntityItems;
        public IEnumerable entityItems()
        {
            var result = new List<EntityItem>();
            var current = Templates.Current;
            if (current == null || string.IsNullOrEmpty(current.Screen))
                return result;

            var info = PX.Api.ScreenUtils.ScreenInfo.TryGet(current.Screen);
            if (info == null)
                return result;

            var graphType = PXBuildManager.GetType(info.GraphName, false);
            if (graphType == null)
                return result;

            var graph = (PXGraph)Activator.CreateInstance(graphType);
            var systemAdded = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

            // Add General Info node for system fields
            result.Add(new EntityItem
            {
                Key = "GENERALINFO",
                Name = "General Info",
                Path = "GeneralInfo",
                Icon = "Folder",
                ParentKey = null
            });

            foreach (var kv in info.Views)
            {
                var viewName = kv.Key;
                if (viewName.StartsWith("$", StringComparison.OrdinalIgnoreCase) ||
                    viewName.StartsWith("_CACHE#", StringComparison.OrdinalIgnoreCase) ||
                    viewName.StartsWith("_", StringComparison.OrdinalIgnoreCase))
                    continue;

                var layoutFields = (kv.Value ?? Array.Empty<string>())
                    .Distinct(StringComparer.OrdinalIgnoreCase)
                    .ToList();

                if (!graph.Views.ContainsKey(viewName))
                    continue;

                var cache = graph.Views[viewName]?.Cache;
                if (cache == null) continue;

                var dacType = cache.GetItemType();
                var dacName = dacType?.Name ?? string.Empty;

                // ViewName as parent node
                result.Add(new EntityItem
                {
                    Key = viewName,
                    Name = viewName,
                    Path = viewName,
                    Icon = "Folder",
                    ParentKey = null
                });

                var fieldsToProcess = layoutFields.Count > 0 ? layoutFields : cache.Fields.ToList();
                var addedInThisView = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

                foreach (var field in fieldsToProcess)
                {
                    if (!string.IsNullOrEmpty(dacName) &&
                        string.Equals(field, dacName, StringComparison.OrdinalIgnoreCase))
                        continue;

                    if (!addedInThisView.Add(field)) continue;

                    var uiAttr = cache.GetAttributes(field).OfType<PXUIFieldAttribute>().FirstOrDefault();
                    var displayName = uiAttr?.DisplayName ?? field;

                    if (IsSystemField(field))
                    {
                        // System field move to General Info
                        if (systemAdded.Add(field))
                        {
                            result.Add(new EntityItem
                            {
                                Key = $"GENERALINFO.{field}",
                                Name = displayName,
                                Path = $"[{field}]",
                                Icon = "Doc",
                                ParentKey = "GENERALINFO"
                            });
                        }
                        continue;
                    }

                    // Data Field as child node (error)
                    result.Add(new EntityItem
                    {
                        Key = $"{viewName}.{field}",
                        Name = displayName,
                        Path = $"[{field}]",
                        Icon = "Doc",
                        ParentKey = viewName
                    });
                }
            }
            return result;
        }

        private static bool IsSystemField(string fieldName)
        {
            string[] systemFields =
            {
        "CreatedByID", "CreatedDateTime", "CreatedByScreenID",
        "LastModifiedByID", "LastModifiedDateTime", "LastModifiedByScreenID",
        "NoteID", "tstamp"
    };
            return systemFields.Contains(fieldName, StringComparer.OrdinalIgnoreCase);
        }

Code for UI:


<px:PXRichTextEdit runat="server" ID="edBody" EncodeInstructions="true" AllowLoadTemplate="true" AllowPlaceholders="true" AllowInsertParameter="true" AllowInsertPrevParameter="True" AllowAttached="true" AllowSearch="true" AllowMacros="true" AllowSourceMode="true" FileAttribute="embedded" DataField="Body" Style='width:100%;'>
    <AutoSize Enabled="True" MinHeight="216" />
    <LoadTemplate TypeName="PX.SM.SMNotificationMaint" ViewName="NotificationTemplate" Size="M" DataMember="NotificationsRO" ValueField="notificationID" TextField="Name" DataSourceID="ds" />
    <InsertDatafield DataSourceID="ds" DataMember="EntityItems" ValueField="Path" TextField="Name" ImageField="Icon"  />
    <InsertDatafieldPrev DataSourceID="ds" DataMember="PreviousEntityItems" ValueField="Path" TextField="Name" ImageField="Icon" />
</px:PXRichTextEdit>