我之前在Stack Overflow上获得了一些关于递归产品类别树视图的帮助,这是有效的:
实体模型:
public class ProductCategory
{
public int Id { get; set; }
public int SortOrder { get; set; }
public string Title { get; set; }
[ForeignKey(nameof(ParentCategory))]
public int? ParentId { get; set; }
public ProductCategory ParentCategory { get; set; } //nav.prop to parent
public ICollection<ProductCategory> Children { get; set; } //nav. prop to children
public List<ProductInCategory> ProductInCategory { get; set; }
}
控制器:
var categories = _context.ProductCategories.Include(e => e.Children).ToList();
var topLevelCategories = categories.Where(e => e.ParentId == null);
return View(topLevelCategories);
查看:
@if (Model != null)
{
foreach (var item in Model)
{
<li>
@item.Title
<ul>
@Html.Partial("_CategoryRecursive.cshtml", item.Children)
</ul>
</li>
}
}
但是当我尝试将此设置转换为我的viewmodel(并添加用于计算每个类别中的产品的属性,以及没有任何类别连接的产品列表)时......:
视图模型:
public class ViewModelProductCategory
{
public int Id { get; set; }
public int? ParentId { get; set; }
public string Title { get; set; }
public int SortOrder { get; set; }
public string ProductCountInfo
{
get
{
return Products != null && Products.Any() ? Products.Count().ToString() : "0";
}
}
public ViewModelProductCategory ParentCategory { get; set; } // Nav.prop. to parent
public IEnumerable<ViewModelProductCategory> Children { get; set; } // Nav.prop. to children
public List<ViewModelProduct> Products { get; set; } // Products in this category
public List<ViewModelProduct> OrphanProducts { get; set; } // Products with no reference in ProductInCategory
}
控制器:
var VMCategories = _context.ProductCategories
.Include(e => e.Children)
.OrderBy(s => s.SortOrder)
.Where(r => r.ParentId == null) // only need root level categories in the View
.Select(v => new ViewModelProductCategory
{
Id = v.Id,
ParentId = v.ParentId,
Title = v.Title,
SortOrder = v.SortOrder,
// get products without a category:
OrphanProducts = v.ProductInCategory
.Where(o => !_context.ProductsInCategories.Any(pc => o.Id == pc.ProductId))
.Select(orph => new ViewModelProduct
{
Id = orph.Product.Id,
Title = orph.Product.Title,
Price = orph.Product.Price,
Info = orph.Product.Info,
SortOrder = orph.SortOrder
})
.OrderBy(s => s.SortOrder)
.ToList()
})
.ToList();
return View(VMCategories);
查看:
@if (Model != null)
{
foreach (var item in Model)
{
<li>
@item.Title (@item.ProductCountInfo)
<ul>
@Html.Partial("_CategoryRecursive.cshtml", item.Children)
</ul>
</li>
}
}
......它将不再起作用。视图确实呈现,但它只显示根类别。似乎我的修改后的查询不会获得任何子类别。当我检查查询结果时,Children属性为null。
修改
我将使用@ Rainman的解决方案,并将我的查询.Select
更改为包含Children = v.Children,
,并改变我的viewmodel导航属性:
public ProductCategory ParentCategory { get; set; } //nav.prop to parent
public ICollection<ProductCategory> Children { get; set; } //nav. prop to children
我还创建了新的viewmodel CategoryRecursiveModel
并将我的观点改为:
@model IEnumerable<MyStore.Models.ViewModels.ViewModelProductCategory>
<ul>
@if (Model != null)
{
foreach (var item in Model)
{
<li>
@item.Title (@item.ProductCountInfo)
<ul>
@Html.Partial("_CategoryRecursive.cshtml", new CategoryRecursiveModel
{
Children = item.Children.ToList();
})
</ul>
</li>
}
}
</ul>
现在我遇到了InvalidOperationException,因为视图期望有一个IEnumerable的ViewModelProductCategory,但是接收到了CategoryRecursiveModel。
答案 0 :(得分:0)
因为您没有为第二个查询选择Children
;
var VMCategories = _context.ProductCategories
.Include(e => e.Children)
.OrderBy(s => s.SortOrder)
.Where(r => r.ParentId == null) // only need root level categories in the View
.Select(v => new ViewModelProductCategory
{
Id = v.Id,
Children = v.Children, // Select it
ParentId = v.ParentId,
Title = v.Title,
SortOrder = v.SortOrder,
// get products without a category:
OrphanProducts = v.ProductInCategory
.Where(o => !_context.ProductsInCategories.Any(pc => o.Id == pc.ProductId))
.Select(orph => new ViewModelProduct
{
Id = orph.Product.Id,
Title = orph.Product.Title,
Price = orph.Product.Price,
Info = orph.Product.Info,
SortOrder = orph.SortOrder
})
.OrderBy(s => s.SortOrder)
.ToList()
})
.ToList();
public ProductCategory ParentCategory { get; set; } //nav.prop to parent public ICollection<ProductCategory> Children { get; set; } //nav. prop to children
此外,导航属性仅适用于非ViewModelProductCategory
模型类或其他类的EF实体。
修改强>
为_CategoryRecursive
视图创建模型类;
public class CategoryRecursiveModel
{
public List<ProductCategory> Children { get; set; }
}
改变主视图;
@if (Model != null)
{
foreach (var item in Model)
{
<li>
@item.Title (@item.ProductCountInfo)
<ul>
@Html.Partial("_CategoryRecursive.cshtml", new CategoryRecursiveModel
{
Children = item.Children.ToList();
})
</ul>
</li>
}
}