score:2

Accepted answer

You can pair up each item with category IDs, like this:

var items = _umbracoHelper.GetPage(ItemsPage.ModelTypeAlias).Children
    .Select(c => new {
        Child = c
    ,   CategoryIds = c
           .GetPropertyValue<IEnumerable<IPublishedContent>>(UmbracoAlias.Item.Categories)
           .Select(y => y.Id)
           .ToList()
    })
    .Where(x => level1Category == 0     || x.CategoryIds.Contains(level1Category))
    .Where(x => !level2Categories.Any() || x.CategoryIds.Intersect(level2Categories.AsEnumerable()).Any())
    .Where(x => !level3Categories.Any() || x.CategoryIds.Intersect(level3Categories.AsEnumerable()).Any())
    .Select(x => x.Child);

This does the filtering on children paired up with their category IDs, and then keeps only the Child object in the final projection.

You could further simplify this by combining all three Where clauses:

var items = _umbracoHelper.GetPage(ItemsPage.ModelTypeAlias).Children
    .Where(c => {
        var categoryIds = c
           .GetPropertyValue<IEnumerable<IPublishedContent>>(UmbracoAlias.Item.Categories)
           .Select(y => y.Id)
           .ToList();
        if (level1Category != 0 && !categoryIds.Contains(level1Category)) {
            return false;
        }
        if (level2Categories.Any() && !categoryIds.Intersect(level2Categories.AsEnumerable()).Any()) {
            return false;
        }
        if (level3Categories.Any() && !categoryIds.Intersect(level3Categories.AsEnumerable()).Any()) {
            return false;
        }
        return true;
    });

Related Articles