MVC5 Razor html.dropdownlistfor set 当值在数组中时被选中

Posted

技术标签:

【中文标题】MVC5 Razor html.dropdownlistfor set 当值在数组中时被选中【英文标题】:MVC5 Razor html.dropdownlistfor set selected when value is in array 【发布时间】:2016-09-21 07:50:44 【问题描述】:

我正在使用 C# 和 .NET Framework 4.6.1 开发一个 ASP.NET MVC 5 应用程序。

我有这个View

@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);
        
    

Models.AggregationLevelConfiguration 是:

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"); 

但我无法在new SelectList(codeTypes, "Id", "Name");new SelectList(helperCodeTypes, "Id", "Name"); 中设置它,因为所选值在Configurations 数组中:字段AggregationLevelConfiguration.CodeTypeAggregationLevelConfiguration.HelperCodeType

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

如何设置选定的值?

【问题讨论】:

在循环中使用DropDownListFor() 是一个不幸的限制。您需要在每次迭代中生成一个新的MutliSelectList(在构造函数中设置selectedValues 属性),或者(更好)使用EditorTemplate for typeof AggregationLevelConfiguration 并将SelectList 作为@ 传递给模板987654339@ 谢谢。我明白我必须使用东西,但我不知道如何使用它们。 我试图找到一个答案,我在大约 6 个月前给出了两个选项的代码,但没有任何运气。如果我找不到它,我会在一个小时左右添加一个答案 - 但以下应该有效 - @Html.DropDownListFor(m =&gt; m.Configurations[0].HelperCodeType, new SelectList(Model.HelperCodeTypeItems, "Value", "Text", Model.Configurations[0].HelperCodeType, new ... ) 我正在研究使用 jQuery 选择选项的解决方案。 是的,这行得通。谢谢。 【参考方案1】:

不幸的是,@Html.DropDownListFor() 在循环中渲染控件时的行为与其他帮助程序略有不同。这之前已在 CodePlex 上报告为问题(不确定是错误还是限制)

有 2 个选项可以解决这个问题,以确保根据模型属性选择正确的选项

选项 1(使用 EditorTemplate

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

@model yourAssembly.AggregationLevelConfiguration
@Html.DropDownListFor(m => m.HelperCodeType, (SelectList)ViewData["CodeTypeItems"])
.... // other properties of AggregationLevelConfiguration

然后在主视图中,将SelectList 传递给EditorTemplate 作为additionalViewData

@using (Html.BeginForm())

  ...
  @Html.EditorFor(m => m.Configurations , new  CodeTypeItems = Model.CodeTypeItems )
  ...

选项2(在每次迭代中生成一个新的SelectList并设置selectedValue

在此选项中,您的属性CodeTypeItems 应该是IEnumerable&lt;GenericIdNameType&gt;,而不是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 属性

【讨论】:

使用选项 2,您节省了我的时间!之前,我使用了一个 hacky javascript 循环来遍历我所有的 DropDownLists 并从隐藏字段中手动设置选定的值。【参考方案2】:

我编写这个类是为了解决在 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; 
    

public IEnumerable<SelectOption> getOrderTypes()

    List<SelectOption> orderTypes = new List<SelectOption>();
                        if (this.orderType == "OptionText")
                        
                            orderTypes.Add(new SelectOption()  Value = "1", Text = "OptionText", Selected = true );
                         else
                        
                            orderTypes.Add(new SelectOption()  Value = "2", Text = "OptionText2" );
                        

并使用它:

@
    Login_page.Models.HTMLSelect selectElement = new Login_page.Models.HTMLSelect("order-types", "order-types");


@Html.Raw(selectElement.GenerateSelect(Model.getOrderTypes()));

【讨论】:

【参考方案3】:

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

我们在顶部看到了这一行:

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" )

我们在我的 ViewData 中有一个与 lambda 表达式的选择器同名的属性,并且由于某种原因导致下拉菜单在没有选择任何选项的情况下呈现。

我们将 ViewData 中的名称更改为 ViewData["ExitFromTrustDeed2"],使其按预期工作。

虽然很奇怪。

【讨论】:

以上是关于MVC5 Razor html.dropdownlistfor set 当值在数组中时被选中的主要内容,如果未能解决你的问题,请参考以下文章

MVC5 Razor html.dropdownlistfor set 当值在数组中时被选中

ASP.NET MVC5 每个 Razor 页面在第一次加载时非常慢

MVC 5 Razor 视图未将 bool 绑定到输入

ASP.NET MVC5 视图预编译

某些 Razor 视图未发布

MVC5-4 ViewResult