using System.Collections.Generic;
public class AppCategoryDataModel
public int AppCategoryId { get; set; }
public int? ParentAppCategoryId { get; set; }
public string AppCategoryName { get; set; }
public int? ProtocolId { get; set; }
public string ProtocolTitle { get; set; }
public class IAppCategory
int? ProtocolCount { get; }
List<ProtocolDetails> ProtocolData { get; }
public class FirstLevelCategory : IAppCategory
public int Id { get; set; }
public string Name { get; set; }
public int? ProtocolCount { get; set; }
public List<ProtocolDetails> ProtocolData { get; set; }
public List<SecondLevelCategory> SubCategories { get; set; }
public bool IsExpand { get; set; }
public bool IsExpandAll { get; set; }
public bool IsCategoryHierarchyExpanded { get; set; }
public class SecondLevelCategory : IAppCategory
public int Id { get; set; }
public string Name { get; set; }
public int? ProtocolCount { get; set; }
public List<ProtocolDetails> ProtocolData { get; set; }
public List<ThirdLevelCategory> SubCategories { get; set; }
public bool IsExpand { get; set; }
public bool? ToggleThis { get; set; }
public class ThirdLevelCategory : IAppCategory
public int Id { get; set; }
public string Name { get; set; }
public int? ProtocolCount { get; set; }
public List<ProtocolDetails> ProtocolData { get; set; }
public bool? ToggleThis { get; set; }
public class ProtocolDetails
public int Id { get; set; }
public string Title { get; set; }
public static void Main()
var appCategoryList = new List<AppCategoryDataModel>()
new() { AppCategoryId = 4844, ParentAppCategoryId = null, AppCategoryName = "ItemResearch", ProtocolId = 5164, ProtocolTitle="ABC: Evaluation" },
new() { AppCategoryId = 4844, ParentAppCategoryId = null, AppCategoryName = "ItemResearch", ProtocolId = null, ProtocolTitle=""},
new() { AppCategoryId = 4845, ParentAppCategoryId = null, AppCategoryName = "ItemHostpital", ProtocolId = null, ProtocolTitle="" },
new() { AppCategoryId = 4845, ParentAppCategoryId = null, AppCategoryName = "ItemHostpital", ProtocolId =5162 , ProtocolTitle="ABC: 3/28/20" },
new() { AppCategoryId = 4845, ParentAppCategoryId = null, AppCategoryName = "ItemHostpital", ProtocolId =5164 , ProtocolTitle="ABC: Evaluation" },
new() { AppCategoryId = 4845, ParentAppCategoryId = null, AppCategoryName = "ItemHostpital", ProtocolId =5165 , ProtocolTitle="ABC: section", },
new() { AppCategoryId = 4845, ParentAppCategoryId = null, AppCategoryName = "ItemHostpital", ProtocolId =5192 , ProtocolTitle="ABC: 3/31/20", },
new() { AppCategoryId = 4846, ParentAppCategoryId = null, AppCategoryName = "Contact information", ProtocolId = null, ProtocolTitle="", },
new() { AppCategoryId = 4846, ParentAppCategoryId = null, AppCategoryName = "Contact information", ProtocolId =5164 , ProtocolTitle="ABC: Evaluation", },
new() { AppCategoryId = 4852, ParentAppCategoryId = null, AppCategoryName = "UP", ProtocolId =null , ProtocolTitle="", },
new() { AppCategoryId = 4852, ParentAppCategoryId = null, AppCategoryName = "UP", ProtocolId = 5164, ProtocolTitle="ABC: Evaluation", },
new() { AppCategoryId = 5023, ParentAppCategoryId = null, AppCategoryName = "Call survival guide", ProtocolId = null, ProtocolTitle="" },
new() { AppCategoryId = 5023, ParentAppCategoryId = null, AppCategoryName = "Call survival guides", ProtocolId =5164 , ProtocolTitle="ABC: Evaluation" },
new() { AppCategoryId = 5085, ParentAppCategoryId = null, AppCategoryName = "OE", ProtocolId =null, ProtocolTitle="" },
new() { AppCategoryId = 5085, ParentAppCategoryId = null, AppCategoryName = "OE", ProtocolId =5164 , ProtocolTitle="ABC: Evaluation" },
new() { AppCategoryId = 5099, ParentAppCategoryId = null, AppCategoryName = "OEM", ProtocolId =null , ProtocolTitle=null },
new() { AppCategoryId = 5334, ParentAppCategoryId = 5085, AppCategoryName = "mmkk update", ProtocolId =null , ProtocolTitle= null },
new() { AppCategoryId = 5336, ParentAppCategoryId = 5085, AppCategoryName = "xdgdrg", ProtocolId =null , ProtocolTitle=null },
new() { AppCategoryId = 5348, ParentAppCategoryId = 5023, AppCategoryName = "test", ProtocolId =null , ProtocolTitle=null },
new() { AppCategoryId = 5341, ParentAppCategoryId = 5023, AppCategoryName = "New Category Level-1", ProtocolId =null , ProtocolTitle= null },
new() { AppCategoryId = 5349, ParentAppCategoryId = 5341, AppCategoryName = "New Category Level-2", ProtocolId =null , ProtocolTitle= null },
new() { AppCategoryId = 5352, ParentAppCategoryId = 5348, AppCategoryName = "New category3", ProtocolId =null , ProtocolTitle= null },
.OrderBy(ap => ap.AppCategoryName)
Dictionary<int, FirstLevelCategory> dictCategories = new();
var firstLevelCategories = GetSubCategories<FirstLevelCategory>(appCategoryList, null);
foreach (var category in firstLevelCategories)
dictCategories.Add(category.Id, category);
foreach (var category in dictCategories.Values)
Console.WriteLine(category.Name);
foreach (var protocol in category.ProtocolData)
Console.WriteLine("\t" + protocol.Title);
foreach (var subCategory in category.SubCategories)
Console.WriteLine("\t\t" + subCategory.Name);
foreach (var subSubCategory in subCategory.SubCategories)
Console.WriteLine("\t\t\t" + subSubCategory.Name);
private static List<T> GetSubCategories<T>(List<AppCategoryDataModel> appCategories, int? parentAppCategoryId) where T : IAppCategory, new()
if (!appCategories.Any(ac => ac.ParentAppCategoryId == parentAppCategoryId))
var subCategories = appCategories
.Where(ac => ac.ParentAppCategoryId == parentAppCategoryId)
.GroupBy(ac => ac.AppCategoryId)
Name = gr.First().AppCategoryName,
.Where(ac => ac.ProtocolId != null)
.Select(ac => new ProtocolDetails
Id = ac.ProtocolId.Value,
if (typeof(T) == typeof(FirstLevelCategory))
.Select(sc => new FirstLevelCategory
ProtocolData = sc.ProtocolData,
ProtocolCount = sc.ProtocolData.Count,
SubCategories = GetSubCategories<SecondLevelCategory>(appCategories, sc.Id),
if (typeof(T) == typeof(SecondLevelCategory))
.Select(sc => new SecondLevelCategory
ProtocolData = sc.ProtocolData,
ProtocolCount = sc.ProtocolData.Count,
SubCategories = GetSubCategories<ThirdLevelCategory>(appCategories, sc.Id),
if (typeof(T) == typeof(ThirdLevelCategory))
.Select(sc => new ThirdLevelCategory
ProtocolData = sc.ProtocolData,
ProtocolCount = sc.ProtocolData.Count