C# 值位于数组中时所选集合的MVC5 Razor html.DropDownList

C# 值位于数组中时所选集合的MVC5 Razor html.DropDownList,c#,asp.net-mvc,razor,C#,Asp.net Mvc,Razor,我正在开发一个ASP.NETMVC5应用程序,使用C#和.NETFramework 4.6.1 我有一个视图: @model MyProject.Web.API.Models.AggregationLevelConfViewModel [...] @Html.DropDownListFor(m => m.Configurations[0].HelperCodeType, (SelectList)Model.HelperCodeTypeItems, new { id = "Configu

我正在开发一个ASP.NETMVC5应用程序,使用C#和.NETFramework 4.6.1

我有一个
视图

@model MyProject.Web.API.Models.AggregationLevelConfViewModel

[...]

@Html.DropDownListFor(m => m.Configurations[0].HelperCodeType, (SelectList)Model.HelperCodeTypeItems, new { id = "Configurations[0].HelperCodeType" })
ViewModel
是:

public class AggregationLevelConfViewModel
{
    private readonly List<GenericIdNameType> codeTypes;
    private readonly List<GenericIdNameType> helperCodeTypes;

    public IEnumerable<SelectListItem> CodeTypeItems
    {
        get { return new SelectList(codeTypes, "Id", "Name"); }
    }

    public IEnumerable<SelectListItem> HelperCodeTypeItems
    {
        get { return new SelectList(helperCodeTypes, "Id", "Name"); }
    }

    public int ProductionOrderId { get; set; }

    public string ProductionOrderName { get; set; }

    public IList<Models.AggregationLevelConfiguration> Configurations { get; set; }

    public AggregationLevelConfViewModel()
    {
        // Load CodeTypes to show it as a DropDownList
        byte[] values = (byte[])Enum.GetValues(typeof(CodeTypes));

        codeTypes = new List<GenericIdNameType>();
        helperCodeTypes = new List<GenericIdNameType>();

        for (int i = 0; i < values.Length; i++)
        {
            GenericIdNameType cType = new GenericIdNameType()
            {
                Id = values[i].ToString(),
                Name = EnumHelper.GetDescription((CodeTypes)values[i])
            };

            if (((CodeTypes)values[i]) != CodeTypes.NotUsed)
                codeTypes.Add(cType);

            helperCodeTypes.Add(cType);
        }
    }
}
public class AggregationLevelConfiguration
{
    public byte AggregationLevelConfigurationId { get; set; }
    public int ProductionOrderId { get; set; }
    public string Name { get; set; }
    public byte CodeType { get; set; }
    public byte HelperCodeType { get; set; }
    public int PkgRatio { get; set; }
    public int RemainingCodes { get; set; }
}
我需要在以下属性中设置选定值:

public IEnumerable<SelectListItem> CodeTypeItems
{
    get { return new SelectList(codeTypes, "Id", "Name"); }
}

public IEnumerable<SelectListItem> HelperCodeTypeItems
{
    get { return new SelectList(helperCodeTypes, "Id", "Name"); }
}
public IEnumerable CodeTypeItems
{
获取{returnnewselectlist(代码类型,“Id”,“Name”);}
}
公共IEnumerable HelperCodeTypeItems
{
获取{returnnewselectlist(helperCodeTypes,“Id”,“Name”);}
}
但是我不能在
newselectlist(代码类型,“Id”,“Name”)中设置它
新建选择列表(帮助代码类型,“Id”、“名称”)因为所选值位于
配置中
数组:字段
AggregationLevelConfiguration.CodeType
AggregationLevelConfiguration.HelperCodeType

我想我必须在视图中设置所选的值,但我不知道怎么做


如何设置所选值?

不幸的是
@Html.DropDownListFor()
在循环中呈现控件时,其行为与其他帮助程序略有不同。这以前在CodePlex上被报告为一个问题(不确定这是一个bug还是一个限制)

are 2选项可解决此问题,以确保根据模型特性选择正确的选项

选项1(使用
编辑器模板

为集合中的类型创建自定义
EditorTemplate
。在
/Views/Shared/EditorTemplates/AggregationLevelConfiguration.cshtml
中创建分部文件(注意名称必须与类型名称匹配

@model yourAssembly.AggregationLevelConfiguration
@Html.DropDownListFor(m => m.HelperCodeType, (SelectList)ViewData["CodeTypeItems"])
.... // other properties of AggregationLevelConfiguration
然后在主视图中,将
选择列表
传递给
编辑器或模板
作为
附加视图数据

@using (Html.BeginForm())
{
  ...
  @Html.EditorFor(m => m.Configurations , new { CodeTypeItems = Model.CodeTypeItems })
  ...
选项2(在每次迭代中生成一个新的
SelectList
,并设置
selectedValue

在此选项中,您的属性
CodeTypeItems
应该是
IEnumerable
,而不是
SelectList
(或者只是将
codeTypes
设置为公共属性)。然后在主视图中

@Html.DropDownListFor(m => m.Configurations[0].HelperCodeType, new SelectList(Model.CodeTypeItems, "Id", "Name", Model.Configurations[0].HelperCodeType)

旁注:无需使用
new{id=“Configurations[0].HelperCodeType”
-已生成
DropDownListFor()
方法,该方法已生成
id
attribute

,我编写该类是为了克服在html选择列表中选择选项时遇到的问题。我希望它能帮助某些人

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;

namespace Login_page.Models
{
    public class HTMLSelect
    {
        public string id { get; set; }
        public IEnumerable<string> @class { get; set; }
        public string name { get; set; }
        public Boolean required { get; set; }
        public string size { get; set; }
        public IEnumerable<SelectOption> SelectOptions { get; set; }

        public HTMLSelect(IEnumerable<SelectOption> options)
        {

        }

        public HTMLSelect(string id, string name)
        {
            this.id = id;
            this.name = name;
        }

        public HTMLSelect(string id, string name, bool required, IEnumerable<SelectOption> options)
        {
            this.id = id;
            this.name = name;
            this.required = required;
        }

        private string BuildOpeningTag()
        {
            StringBuilder text = new StringBuilder();
            text.Append("<select");
            text.Append(this.id != null ? " id=" + '"' + this.id + '"' : "");
            text.Append(this.name != null ? " name=" + '"' + this.name + '"' : "");
            text.Append(">");
            return text.ToString();

        }

        public string GenerateSelect(IEnumerable<SelectOption> options)
        {
            StringBuilder selectElement = new StringBuilder();
            selectElement.Append(this.BuildOpeningTag());
            foreach (SelectOption option in options)
            {
                StringBuilder text = new StringBuilder();
                text.Append("\t");
                text.Append("<option value=" + '"' + option.Value + '"');
                text.Append(option.Selected != false ? " selected=" + '"' + "selected" + '"' + ">" : ">");
                text.Append(option.Text);
                text.Append("</option>");
                selectElement.Append(text.ToString());
            }
            selectElement.Append("</select");
            return selectElement.ToString();
        }
    }

    public class SelectOption
    {
        public string Text { get; set; }
        public Boolean Selected { get; set; }
        public string Value { get; set; }
    }
}

我留下这个,以防它对其他人有帮助。我有一个非常类似的问题,没有一个答案对我有帮助

我们在顶部看到了这条线:

IEnumerable<SelectListItem> exitFromTrustDeed = (ViewData["ExitFromTrustDeed"] as IEnumerable<string>).Select(e => new SelectListItem() { 
    Value = e, 
    Text = e,
    Selected = Model.ExitFromTrustDeed == e
});
我的ViewData中有一个与lambda表达式的选择器同名的属性,出于某种原因,该属性使下拉列表在不选择任何选项的情况下呈现

我们将ViewData中的名称更改为
ViewData[“ExitFromTrustDeed2”]
,这使它按预期工作


但是很奇怪。

在循环中使用
DropDownListFor()
是一个不幸的限制。您需要在每次迭代中生成一个新的
MutliSelectList
(在构造函数中设置
selectedValues
属性),或者(更好),使用
EditorTemplate
作为
AggregationLevelConfiguration
的类型,并将
SelectList
作为
AdditionalViewData
传递给模板。我知道我必须使用一些东西,但我不知道如何使用它们。我正在试图找到一个关于这两个选项的代码的答案,大约6个月前但是运气不好。如果我找不到答案,我会在一个小时左右添加一个答案-但是下面的方法应该有效-
@Html.DropDownListFor(m=>m.Configurations[0]。HelperCodeType,new SelectList(Model.HelperCodeTypeItems,“Value”,“Text”,Model.Configurations[0]。HelperCodeType,new{…})
我正在研究一个使用jQuery选择选项的解决方案。是的,这很有效。谢谢。使用选项2,您节省了我的一天!之前,我使用了一个黑客JavaScript循环来迭代我的所有下拉列表,并从隐藏字段手动设置所选值。
@{
    Login_page.Models.HTMLSelect selectElement = new Login_page.Models.HTMLSelect("order-types", "order-types");

}
@Html.Raw(selectElement.GenerateSelect(Model.getOrderTypes()));
IEnumerable<SelectListItem> exitFromTrustDeed = (ViewData["ExitFromTrustDeed"] as IEnumerable<string>).Select(e => new SelectListItem() { 
    Value = e, 
    Text = e,
    Selected = Model.ExitFromTrustDeed == e
});
@Html.DropDownListFor(m => m.ExitFromTrustDeed, exitFromTrustDeed, new { @class = "form-control" })