@Html.DropdownList 显示类别 >> 子类别 >> 子类别作为文本值

@Html.DropdownList to show Category >> Subcategory >> Subcategory as text value

我有一个简单的 Category class 来创建一个自引用 table。

public class Category
{
    public int CategoryId{get; set;}
    public string Name {get;set;
    public int? ParentId {get;set}
    public virtual Category Parent {get;set}

    public virtual ICollection<Category> Children {get;set;}
}

并且由 EF 生成的创建视图具有新类别名称的开箱即用区域:

@Html.LabelFor(model => model.Name, new {@class = "control-label"})
@Html.EditorFor(model => model.Name,"", new{@class="form-control"}

以及预填充父类别选择的区域

@Html.LabelFor(model => model.ParentId, "Parent Category", new {@class = "control-label"})
@Html.DropdownList("ParentId", null, new {@class ="form-control})

这允许具有多个嵌套子类别的类别和嵌套在其他子类别下的其他子类别,等等......等等......

创建视图允许您创建新类别并使用 @Html.DropdownList 分配父类别,该类别提取所有类别的文本值但仅列出实际类别或子类别名称。

有没有办法更改 @Html.DropdownList 中的显示值以显示分层树而不是单个父值?

因此,@Html.Dropdownlist 显示 "AAA Batteries"(新类别的父类别的值),它显示父类别的完整层次值:

Electronic Supplies >> Batteries >> AAA Batteries

这当然是一个名为 "Electronic Supplies" 的类别,其子类别为 "Batteries",子类别为 "AAA Batteries"。

您的模型中需要一个方法来为您生成此名称。类似于:

public class Category
{
    public int CategoryId {get; set;}
    public int ParentId {get; set;}
    public string Name {get; set;}

    public string GetFullCategoryName()
    {
        string result = this.Name;

        // note: I removed the argument because it's class member.
        Category parent = this.GetParent(); // null for top level Categories

        while (parent != null)
        {
            result = parent.Name + " >> " + result;
            parent = GetParent(parent.ParentId);
        }

        return result;
    }

    public Category GetParent()
    {
        // note: I just made this up, you would use whatever EF method you have...
        return EF.GetEntity<Category>(this.ParentId);
    }
}

当然你还需要一个GetParent方法...

编辑:

这是一个使用它的示例(假设有一个模型带有 CategoryId 属性 和 GetAllCategories 方法):

@Html.DropDownListFor(x => x.CategoryId, Model.GetAllCategories().Select(c => new SelectListItem() { Text = c.GetFullCategoryName(), Value = c.CategoryId }))

编辑 2: 我更改了上面的代码以显示整个 class,也许这样更有意义?