public static GroupTree <T> RetrieveGrouped <T>(DatasourceRequest request, IQueryable <T> filteredWithPredefinedFilters, Func <T, object> uniqueKeyExpression, List <AggregatorInfo <T> > aggregators, bool forceClosedGroups = false)
        {
            // Apply Dynamic Filter
            var filtered = ApplyDynamicFilterToQueryable(request, filteredWithPredefinedFilters);

            // Groups only (Closed)
            if (forceClosedGroups || request.GroupBy.First().GetGroupsClosed)
            {
                var closedGroupsInfo = RuntimePredicateBuilder.BuildClosedGroupsInfo <T>(request.GroupBy, aggregators);
                return(GroupsHelper.GetAllGroupsClosed <T>(filtered, closedGroupsInfo, new Dictionary <string, string>()));
            }
            // Groups with data
            else
            {
                // Variables initialization
                var dynamicOrderBy = RuntimePredicateBuilder.BuildPredicateForOrdering <T>(request.OrderBy);
                var dynamicGroupBy = RuntimePredicateBuilder.BuildDynamicGroupBy <T>(request.GroupBy);

                return(GroupsHelper.ParseGroups <T>(filtered, dynamicOrderBy, dynamicGroupBy, uniqueKeyExpression, request.StartRow, request.PageSize));
            }
        }
        public string PathAtLevel(int level)
        {
            var path = "";

            for (var i = 0; i < level; i++)
            {
                if (ColumnsToKeys.Count < i + 1)
                {
                    return(path);
                }

                var entry = ColumnsToKeys.ElementAt(i);

                if (!string.IsNullOrEmpty(path))
                {
                    path += GroupsHelper.GroupPathSeperator;
                }

                path += entry.Key + GroupsHelper.GroupValueSeperator + GroupsHelper.ObjectToString(entry.Value).Replace(" ", GroupsHelper.GroupValueSpace);
            }

            return(path);
        }