【问题标题】:MVC5 Razor html.dropdownlistfor set selected when value is in arrayMVC5 Razor html.dropdownlistfor set 当值在数组中时被选中
【发布时间】: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 选择选项的解决方案。
  • 是的,这行得通。谢谢。

标签: c# asp.net-mvc razor


【解决方案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"],使其按预期工作。

    虽然很奇怪。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-02
      相关资源
      最近更新 更多