简体   繁体   English

DropDownList不选择SelectList中的选定项

[英]DropDownListFor not selecting the selected item in the SelectList

I am working on an ASP.NET MVC3 application and I cannot get a DropDownListFor to work with my property in a particular editor view. 我正在使用ASP.NET MVC3应用程序,我无法在特定的编辑器视图中使用DropDownListFor来处理我的属性。

My model is a Person and a person has a property that specifies it's "Person Type". 我的模型是一个Person ,一个人有一个属性,指定它的“人物类型”。 PersonType is a class that contains a name/description and an ID. PersonType是一个包含名称/描述和ID的类。 I can access the available PersonType s within the application through my static/shared class called ApplicationSettings . 我可以通过名为ApplicationSettings静态/共享类访问应用程序中可用的PersonType

In the Edit Template view for my Person I have created a SelectList for debugging purposes: 在我的Person的Edit Template视图中,我创建了一个SelectList用于调试目的:

@ModelType MyNamespace.Person
@Code
    Dim pTypesSelectList As New SelectList(MyNamespace.ApplicationSettings.PersonTypes, "ID", "Name", Model.PersonType.ID)
End Code

I am then providing this SelectList as a parameter to the DropDownListFor that is bound to the PersonType property of my Person . 然后我将此SelectList作为参数提供给DropDownListFor ,该DropDownListFor绑定到PersonPersonType属性。

I am also printing the Selected property of each item in the SelectList for debugging purposes: 我还打印SelectList中每个项目的Selected属性以进行调试:

<div style="text-align: center; margin: 5px 0 0 0;">
    <div>
        @Html.LabelFor(Function(model) model.PersonType)
    </div>
    <div>
        @Html.DropDownListFor(Function(model) model.PersonType, pTypesSelectList)
        @Html.ValidationMessageFor(Function(model) model.PersonType)

        <br />
        <br />
        <!-- The following is debugging code that shows the actual value-->
        @Model.Type.Name
        <br />
        @Model.Type.ID
        <br />
        <br />

        <!--This section is to show that the select list has properly selected the value-->
        @For Each pitem In pTypesSelectList
            @<div>
                @pitem.Text selected: @pitem.Selected
            </div>
        Next
    </div>
</div>

The view is bound to a Person whose PersonType property is "Person Type # 2" and I expect this to be selected; 该视图被绑定到一个Person ,其PersonType属性为“人员类型#2”,我期望这将被选择; however the HTML output of this code looks like this: 但是此代码的HTML输出如下所示:

<div style="text-align: center; margin: 5px 0 0 0;">
    <div>
    <label for="PersonType">PersonType</label>
    </div>
    <div>
        <select id="PersonType" name="PersonType">
            <option value="7e750688-7e00-eeee-0000-007e7506887e">Default Person Type</option>
            <option value="87e5f686-990e-5151-0151-65fa7506887e">Person Type # 1</option>
            <option value="a7b91cb6-2048-4b5b-8b60-a1456ba4134a">Person Type # 2</option>
            <option value="8a147405-8725-4b53-b4b8-3541c2391ca9">Person Type # 3</option>
        </select>
        <span class="field-validation-valid" data-valmsg-for="PersonType" data-valmsg-replace="true"></span>
        <br />
        <br />
        <!-- The following is debugging code that shows the actual value-->
        Person Type # 2
        <br />
        a7b91cb6-2048-4b5b-8b60-a1456ba4134a
        <br />
        <br />
        <!--This section is to show that the select list has properly selected the value-->
        <div>
            Default Person Type selected: False
        </div>
        <div>
            Person Type # 1 selected: False
        </div>
        <div>
            Person Type # 2 selected: True
        </div>
        <div>
            Person Type # 3 selected: False
        </div>
    </div>
</div>

As you can see the printed Selected properties for the items in the SelectList shows that the 3rd item is "Selected". 如您所见,SelectList中项目的已打印Selected属性显示第3项是“Selected”。 But what is driving me crazy is that the option that corresponds with this is Not Selected. 但令我发疯的是,与此相对应的选项是Not Selected。

Generally, the Selected property in SelectList will be totally ignored by the HTML helpers unless there's no other option. 通常,除非没有其他选项,否则HTML帮助程序将完全忽略SelectListSelected属性。 If DropDownListFor can find the value by other means, it will insist on using that value. 如果DropDownListFor可以通过其他方式找到该值,它将坚持使用该值。

In this case, it will use the value of model.PersonType ( .ToString() ) - but that's not what you want, judging by the model.PersonType.ID you pass to the SelectList . 在这种情况下,它将使用model.PersonType.ToString() )的值 - 但这不是您想要的,通过您传递给SelectListmodel.PersonType.ID来判断。

More info in the answer here . 更多信息在这里答案

Workaround 解决方法

One easy workaround that should work would be to set: 一个应该工作的简单解决方法是设置:

ViewData["PersonType"] = model.PersonType.Id. 

The helper looks in ModelState first if it exists - ie on POST. 如果存在,帮助程序首先在ModelState中查找 - 即在POST上。 This should work already, since ModelState["PersonType"] will be populated with the actual selected value that was posted. 这应该已经有效,因为ModelState["PersonType"]将填充已发布的实际选定值。

After ModelState it will look in ViewData - with ViewData["PersonType"] first, and only then ViewData.Model.PersonType . 在ModelState之后,它将在ViewData查找 - 首先使用ViewData["PersonType"] ,然后只查看ViewData.Model.PersonType In other words, you can "override" the value on your model with a value set directly on ViewData . 换句话说,您可以使用直接在ViewData上设置的值“覆盖”模型上的值。

Better (IMO) solution 更好(IMO)的解决方案

The more general, "better practice", way to solve it (which also avoids having a custom model binder in order to translate the POST'ed ID back to PersonType ) is to use a ViewModel instead of working with full models in your view: 更通用的“更好的实践”,解决它的方法(也避免使用自定义模型绑定器将POST的ID转换回PersonType )是使用ViewModel而不是在视图中使用完整模型:

  • Have a PersonTypeID property - instead of PersonType . 有一个PersonTypeID属性 - 而不是PersonType
  • Populate it with PersonType.ID 使用PersonType.ID填充它
  • use this in your view 在您的视图中使用它
    • VB.NET: Html.DropDownListFor(Function(model) model.PersonTypeID) , or Html.DropDownListFor(Function(model) model.PersonTypeID) ,或
    • C#: Html.DropDownListFor(model => model.PersonTypeID) C#: Html.DropDownListFor(model => model.PersonTypeID)
  • When form is POST'ed, translate the ViewModel (including PersonTypeID => PersonType ) back into the actual model in your POST Action. 当表单被POST时,将ViewModel(包括PersonTypeID => PersonType )转换回POST Action中的实际模型。

This may seem like more work, but generally there tend to be many occasions in a project where you need more view-specific representations of your data to avoid too much inline Razor code - so translating from business objects to view models, while it may seem redundant and anti-DRY at times, tends to spare you of a lot of headaches. 这似乎更多的工作,但通常在项目中有很多场合需要更多特定于视图的数据表示,以避免过多的内联Razor代码 - 所以从业务对象转换到视图模型,尽管它看起来很像有时多余和反干,往往会让你免于很多麻烦。

Are you sure that your ModelState for "PersonType" key before rendering the view is empty? 在渲染视图之前,您确定“PersonType”键的ModelState是空的吗? As JimmiTh commented is going to search for the value in the ModelState first. 正如JimmiTh评论的那样,首先要在ModelState中搜索值。 It happened to me too, you can try @Html.DropDownList("PersonTypeFake", Function(model) model.PersonType, pTypesSelectList) and it should select the right option. 它也发生在我身上,你可以试试@Html.DropDownList("PersonTypeFake", Function(model) model.PersonType, pTypesSelectList) ,它应该选择正确的选项。

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

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