DropDownListFor 不绑定在具有重复项的编辑视图上 (List<T>) [英] DropDownListFor not binding on Edit View with repeating items (List<T>)

查看:16
本文介绍了DropDownListFor 不绑定在具有重复项的编辑视图上 (List<T>)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

事情就是这样.我有一个编辑视图,当我打开它时它不会绑定下拉列表的值.

 [非操作]公共列表VraagType() {列表l = new List();SelectListItem a = new SelectListItem();SelectListItem b = new SelectListItem();a.Text = "Meerkeuze";a.Value = "M";b.Text = "打开";b.Value = "O";l.添加(a);l.添加(b);返回 l;}[非操作]公共列表getSchalen() {返回 _db.EvalSchaals.ToList().ToSelectList(q => q.Sch_Naam, q => q.Sch_ID.ToString(), q => q.Sch_ID == -1).ToList();}公共操作结果编辑(int id){ViewData["vraagt​​ype"] = VraagType();ViewData["schaal"] = getSchalen();EvalVragenBlok evb = _db.EvalVragenBloks.First(q => q.Vrbl_ID == id);列表<EvalVragen>ev = _db.EvalVragens.Where(q => q.Vrbl_ID == id).ToList();FlatEvalVragenBlok fevb = Mapper.Map(evb);fevb.Vragen = new List();返回视图(fevb);}

这是来自控制器的代码.

这是 Edit.aspx 视图中的代码

 

编辑

<% using (Html.BeginForm()) {%><%:Html.ValidationSummary(true)%><字段集><legend>字段</legend><legend>字段</legend><div class="editor-label"><%:Html.LabelFor(model =>model.Vrbl_Titel)%>

<div class="editor-field"><%: Html.TextBoxFor(model =>model.Vrbl_Titel)%><%: Html.ValidationMessageFor(model =>model.Vrbl_Titel)%>

<div class="editor-label"><%:Html.LabelFor(model =>model.Sch_ID)%>

<div class="editor-field"><%: Html.DropDownListFor(model => model.Sch_ID, ViewData["schaal"] as List<SelectListItem>, "Selecteer een schaal...") %><%: Html.ValidationMessageFor(model =>model.Sch_ID)%>

<%=Html.ValidationMessageFor(model=>model.Vragen)%><table id="vragentbl"><tr><th></th><th>弗拉格</th><th>排序</th></tr><% if (Model.Vragen != null) { %><% for (int i = 0; i <tr><td><%=i+1%></td><td><%= Html.TextBoxFor(model => model.Vragen[i].Evvr_Vraag, new { style = "width:400px" })%><br/><%=Html.ValidationMessageFor(model=>model.Vragen[i].Evvr_Vraag)%></td><td><%= Html.DropDownListFor(model => model.Vragen[i].Evvr_Type, ViewData["vraagt​​ype"] as List<SelectListItem>, new { style = "width:95px" })%><br/><%=Html.ValidationMessageFor(model=>model.Vragen[i].Evvr_Type)%></td></tr><%}}%><tr><td></td><td><a id="addnew" href="#">Voeg extra keuze toe</a></td><td></td></tr><p><input type="submit" value="保存"/></p></fieldset><%}%>

我有 2 个 List .其中 1 个在表单的非重复部分 (Schalen),另一个 (VraagType) 在重复部分内.

对于 Schalen,一切正常.我打开编辑视图,所有字段都按原样填写.Vrbl_Titel 有它的值,Sch_ID 的下拉列表有它从我随视图发送的对象接收的值,该对象来自数据库.

问题在于重复部分.model.Vragen[i].Evvr_Vraag 的文本框获取其值,并显示 model.Vragen[i].Evvr_Type 的下拉列表,但是,此下拉列表没有获取发送的值物体.它保持它的默认标准值,这是选择列表"中的第一项

我如何从我的Vragen"对象中获取我的价值到下拉菜单中.如果我把值放在一个简单的文本框中

<%= Html.TextBoxFor(model => model.Vragen[i].Evvr_Type)%>

然后文本框确实获得了值.所以问题是下拉值不会改变它的初始值...... MVC 中的错误?

仅供参考,这是对象发送到视图的方式:

 命名空间 MVC2_NASTEST.Models {公共部分类 FlatEvalVragenBlok {公共 int Vrbl_ID { 获取;放;}公共 int Sch_ID { 获取;放;}公共字符串 Vrbl_Titel { 获取;放;}公共列表Vragen { 得到;放;}}}命名空间 MVC2_NASTEST.Models {公共部分类 FlatEvalVragen {公共 int Evvr_ID { 获取;放;}公共 int Vrbl_ID { 获取;放;}公共 int Evvr_rang { 获取;放;}公共字符串 Evvr_Vraag { 获取;放;}公共字符 Evvr_Type { 获取;放;}}}

解决方案

看来这确实是 ASP.NET MVC 2 中的一个错误或至少是不一致的.我检查了它的来源并找到了从 TextBoxFor 调用的 InputHelper() 方法() helper 接收用

计算的默认值

ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData).Model

但是从 DropDownListFor() 助手调用的 SelectInternal() 方法只接收使用 ExpressionHelper.GetExpressionText() 方法找到的控件的名称.

因此 SelectInternal() 尝试使用 MVC 1 中的 ViewData.Eval() 方法查找默认值.众所周知,此方法无法通过数字索引从数组中提取值.

所以在你的情况下是适用的

<%: Html.DropDownListFor(model => model.Sch_ID) %><%= Html.TextBoxFor(model => model.Vragen[i].Evvr_Type)%>

但不是

<%: Html.DropDownListFor(model => model.Vragen[i].Evvr_Type) %>

因为它等价于

<%: Html.DropDownList("Vragen[" + i + "].Evvr_Type") %>

同时我想再次强调一下

<%= Html.TextBoxFor(model => model.Vragen[i].Evvr_Type)%>

不等同于

<%= Html.TextBox("model.Vragen[" + i + "].Evvr_Type")%>

因为后者即使在 MVC 2 中也不能绑定默认值.

可能的解决方法

首先.由于 SelectInternal() 还检查 ModelState 字典,因此您可以在返回视图之前填充此字典.

for (int i=0; i 

这将在发布后由 MVC 自己完成,因此您应该仅在第一次手动完成.

第二.而不是

<%= Html.DropDownListFor(model => model.Vragen[i].Evvr_Type,ViewData["vraagt​​ype"] as List)%>

使用

<%= Html.DropDownListFor(model => model.Vragen[i].Evvr_Type,new SelectList(ViewData["vraagt​​ype"] 作为 IEnumerable, "Value", "Text",Model.Vragen[i].Evvr_Type))%>

ViewData["vraagt​​ype"] 在这种情况下不必包含 SelectListItem 的对象,任何 IEnumerable 就足够了.如有需要,您可以查看 SelectList() 方法说明.

Here is the thing. I have an Edit view, which doesnt bind the dropdowns' value when I open it.

    [NonAction]
    public List<SelectListItem> VraagType() {
        List<SelectListItem> l = new List<SelectListItem>();
        SelectListItem a = new SelectListItem();
        SelectListItem b = new SelectListItem();

        a.Text = "Meerkeuze";
        a.Value = "M";

        b.Text = "Open";
        b.Value = "O";

        l.Add(a);
        l.Add(b);

        return l;
    }

    [NonAction]
    public List<SelectListItem> getSchalen() {
        return _db.EvalSchaals.ToList().ToSelectList(q => q.Sch_Naam, q => q.Sch_ID.ToString(), q => q.Sch_ID == -1).ToList();
    }

    public ActionResult Edit(int id) {
        ViewData["vraagtype"] = VraagType();
        ViewData["schaal"] = getSchalen();

        EvalVragenBlok evb = _db.EvalVragenBloks.First(q => q.Vrbl_ID == id);
        List<EvalVragen> ev = _db.EvalVragens.Where(q => q.Vrbl_ID == id).ToList();

        FlatEvalVragenBlok fevb = Mapper.Map<EvalVragenBlok, FlatEvalVragenBlok>(evb);
        fevb.Vragen = new List<FlatEvalVragen>();

        return View(fevb);
    }

this is the code from the controller.

here is the code from the Edit.aspx view

        <h2>
            Edit</h2>
        <% using (Html.BeginForm()) {%>
        <%: Html.ValidationSummary(true) %>
        <fieldset>
            <legend>Fields</legend>
    <legend>Fields</legend>
            <div class="editor-label">
                <%: Html.LabelFor(model => model.Vrbl_Titel) %>
            </div>
            <div class="editor-field">
                <%: Html.TextBoxFor(model => model.Vrbl_Titel) %>
                <%: Html.ValidationMessageFor(model => model.Vrbl_Titel) %>
            </div>
            <div class="editor-label">
                <%: Html.LabelFor(model => model.Sch_ID) %>
            </div>
            <div class="editor-field">
                <%: Html.DropDownListFor(model => model.Sch_ID, ViewData["schaal"] as List<SelectListItem>, "Selecteer een schaal...") %>
                <%: Html.ValidationMessageFor(model => model.Sch_ID) %>
            </div>
            <%= Html.ValidationMessageFor(model => model.Vragen) %>
            <table id="vragentbl">
                <tr>
                    <th>
                    </th>
                    <th>
                        Vraag
                    </th>
                    <th>
                        Soort
                    </th>
                </tr>
                <% if (Model.Vragen != null) { %>
                <% for (int i = 0; i < Model.Vragen.Count; i++) {  %>
                <tr>
                    <td>
                        <%=i + 1%>
                    </td>
                    <td>
                        <%= Html.TextBoxFor(model => model.Vragen[i].Evvr_Vraag, new { style = "width:400px" })%><br />
                        <%= Html.ValidationMessageFor(model => model.Vragen[i].Evvr_Vraag)%>
                    </td>
                    <td>
                        <%= Html.DropDownListFor(model => model.Vragen[i].Evvr_Type, ViewData["vraagtype"] as List<SelectListItem>, new { style = "width:95px" })%><br />
                        <%= Html.ValidationMessageFor(model => model.Vragen[i].Evvr_Type)%>
                    </td>
                </tr>
                <% }
                   } %>
                <tr>
                    <td>
                    </td>
                    <td>
                        <a id="addnew" href="#">Voeg extra keuze toe</a>
                    </td>
                    <td>
                    </td>
                </tr>
            </table>
            <p>
                <input type="submit" value="Save" />
            </p>
        </fieldset>
        <% } %>

I have 2 List 's. 1 of them is in the non-repeating part of the form (Schalen), the other one (VraagType) is Inside the repeating part.

for Schalen, everything works fine. i open the edit view, and all fields are filled in like it should be. the Vrbl_Titel has its value, and the dropdown of Sch_ID has the value it received from the object which i sent with the view, which came from the DB.

The problem lies in the repeating part. the textbox for model.Vragen[i].Evvr_Vraag get's its value, and the dropdown for model.Vragen[i].Evvr_Type is shown, however, this dropdown does not get the value which was sent in the object. it keeps it's default standard value, which is the first item in the 'selectlist'

how do i get my value from my 'Vragen' object, into the dropdown. if i put the value in a simple textbox

<%= Html.TextBoxFor(model => model.Vragen[i].Evvr_Type)%>

then the textbox does get the value. so the problem is that the dropdownvalue doesnt change form it's initial value... bug in MVC?

just for info, this is how the object(s) look sent to the view:

        namespace MVC2_NASTEST.Models {

            public partial class FlatEvalVragenBlok {
                public int Vrbl_ID { get; set; }
                public int Sch_ID { get; set; }
                public string Vrbl_Titel { get; set; }
                public List<FlatEvalVragen> Vragen { get; set; }
            }
        }

        namespace MVC2_NASTEST.Models {

            public partial class FlatEvalVragen {
                public int Evvr_ID { get; set; }
                public int Vrbl_ID { get; set; }
                public int Evvr_rang { get; set; }
                public string Evvr_Vraag { get; set; }
                public char Evvr_Type { get; set; }
            }
        }

解决方案

It seems this is really a bug or at least inconsistency in ASP.NET MVC 2. I have examined its source and found what InputHelper() method called from TextBoxFor() helper receives default value calculated with

ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData).Model

But SelectInternal() method called from DropDownListFor() helper receives only a name of a control found with ExpressionHelper.GetExpressionText() method.

So SelectInternal() tries to find default value using ViewData.Eval() method from MVC 1. It's known what this method isn't able to extract values from arrays by numeric index.

So in your case are applicable

<%: Html.DropDownListFor(model => model.Sch_ID) %>
<%= Html.TextBoxFor(model => model.Vragen[i].Evvr_Type)%>

but not

<%: Html.DropDownListFor(model => model.Vragen[i].Evvr_Type) %>

because it's equivalent to

<%: Html.DropDownList("Vragen[" + i + "].Evvr_Type") %>

At the same time I want to emphasize again what

<%= Html.TextBoxFor(model => model.Vragen[i].Evvr_Type)%>

isn't equivalent to

<%= Html.TextBox("model.Vragen[" + i + "].Evvr_Type")%>

because latter even in MVC 2 can't bind default value.

Possible workarounds

First. Since SelectInternal() also checks ModelState dictionary you can fill this dictionary before returning the view.

for (int i=0; i < fevb.Vragen.Count(); i++)
    ModelState.Add("Vragen[" + i + "].Evvr_Type", new ModelState
    {
        Value = new ValueProviderResult(fevb.Vragen[i].Evvr_Type, null, 
            CultureInfo.CurrentCulture) 
    });

This will be done by MVC itself after from post, so you should do it manually only first time.

Second. Instead of

<%= Html.DropDownListFor(model => model.Vragen[i].Evvr_Type, 
    ViewData["vraagtype"] as List<SelectListItem>)%>

use

<%= Html.DropDownListFor(model => model.Vragen[i].Evvr_Type, 
    new SelectList(ViewData["vraagtype"] as IEnumerable, "Value", "Text",
        Model.Vragen[i].Evvr_Type))%>

ViewData["vraagtype"] in this case doesn't have to contain objects of SelectListItem, any IEnumerable is enough. You may check SelectList() method description in case of need.

这篇关于DropDownListFor 不绑定在具有重复项的编辑视图上 (List&lt;T&gt;)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆