简体   繁体   English

当值在数组中时,MVC5 Razor html.dropdownlistfor set selected

[英]MVC5 Razor html.dropdownlistfor set selected when value is in array

I'm developing an ASP.NET MVC 5 application, with C# and .NET Framework 4.6.1.我正在开发一个 ASP.NET MVC 5 应用程序,使用 C# 和 .NET Framework 4.6.1。

I have this View :我有这个View

@model MyProject.Web.API.Models.AggregationLevelConfViewModel

[...]

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

The ViewModel is: 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);
        }
    }
}

And Models.AggregationLevelConfiguration is: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; }
}

I need to set selected value in these properties:我需要在这些属性中设置选定的值:

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

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

But I can't set it in new SelectList(codeTypes, "Id", "Name");但是我不能在new SelectList(codeTypes, "Id", "Name");设置它new SelectList(codeTypes, "Id", "Name"); or new SelectList(helperCodeTypes, "Id", "Name");new SelectList(helperCodeTypes, "Id", "Name"); because the selected value are in Configurations array: fields AggregationLevelConfiguration.CodeType and AggregationLevelConfiguration.HelperCodeType .因为所选值位于Configurations数组中:字段AggregationLevelConfiguration.CodeTypeAggregationLevelConfiguration.HelperCodeType

I think I have to set selected value in the View, but I don't know how to do it.我想我必须在视图中设置选定的值,但我不知道该怎么做。

How can I set the selected values?如何设置选定的值?

Unfortunately @Html.DropDownListFor() behaves a little differently than other helpers when rendering controls in a loop.不幸的是, @Html.DropDownListFor()在循环渲染控件时的行为与其他助手略有不同。 This has been previously reported as an issue on CodePlex (not sure if its a bug or just a limitation)这之前已在 CodePlex 上报告为问题(不确定是错误还是限制)

The are 2 option to solve this to ensure the correct option is selected based on the model property有 2 个选项可以解决此问题,以确保根据模型属性选择正确的选项

Option 1 (using an EditorTemplate )选项 1 (使用EditorTemplate

Create a custom EditorTemplate for the type in the collection.为集合中的类型创建自定义EditorTemplate Create a partial in /Views/Shared/EditorTemplates/AggregationLevelConfiguration.cshtml (note the name must match the name of the type/Views/Shared/EditorTemplates/AggregationLevelConfiguration.cshtml创建部分(注意名称必须与类型名称匹配

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

and then in the main view, pass the SelectList to the EditorTemplate as additionalViewData然后在主视图中,将SelectList作为additionalViewData传递给EditorTemplate

@using (Html.BeginForm())
{
  ...
  @Html.EditorFor(m => m.Configurations , new { CodeTypeItems = Model.CodeTypeItems })
  ...

Option 2 (generate a new SelectList in each iteration and set the selectedValue )选项 2 (在每次迭代中生成一个新的SelectList并设置selectedValue

In this option your property CodeTypeItems should to be IEnumerable<GenericIdNameType> , not a SelectList (or just make codeTypes a public property).在此选项中,您的属性CodeTypeItems应该是IEnumerable<GenericIdNameType> ,而不是SelectList (或只是使codeTypes成为公共属性)。 Then in the main view然后在主视图中

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

Side note: there is no need to use new { id = "Configurations[0].HelperCodeType" - the DropDownListFor() method already generated that id attribute旁注:无需使用new { id = "Configurations[0].HelperCodeType" - DropDownListFor()方法已经生成了该id属性

I wrote this class to overcome an issue I was having with selecting an option in an html select list.我编写了这个类来解决我在 html 选择列表中选择一个选项时遇到的问题。 I hope it helps someone.我希望它可以帮助某人。

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; }
    }
}

And

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

And to use it:并使用它:

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

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

I leave this in case it helps someone else.我离开这个以防它帮助别人。 I had a very similar problem and none of the answers helped.我有一个非常相似的问题,但没有一个答案有帮助。

We had in a view this line at the top:我们在顶部看到了这一行:

IEnumerable<SelectListItem> exitFromTrustDeed = (ViewData["ExitFromTrustDeed"] as IEnumerable<string>).Select(e => new SelectListItem() { 
    Value = e, 
    Text = e,
    Selected = Model.ExitFromTrustDeed == e
});

and then below in the view:然后在视图下方:

@Html.DropDownListFor(m => m.ExitFromTrustDeed, exitFromTrustDeed, new { @class = "form-control" })

We had a property in my ViewData with the same name as the selector for the lambda expression and for some reason that makes the dropdown to be rendered without any option selected.我们在我的 ViewData 中有一个与lambda 表达式的选择器同名的属性,并且由于某种原因使得下拉列表在没有选择任何选项的情况下呈现。

We changed the name in ViewData to ViewData["ExitFromTrustDeed2"] and that made it work as expected.我们将 ViewData 中的名称更改为ViewData["ExitFromTrustDeed2"]并使其按预期工作。

Weird though.虽然很奇怪。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM