DropDownList для отсутствия привязки в представлении редактирования с повторяющимися элементами (список <T>) - PullRequest
9 голосов
/ 17 августа 2010

Вот эта вещь. У меня есть вид Edit, который не привязывает значение выпадающего меню, когда я его открываю.

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

это код с контроллера.

вот код из представления Edit.aspx

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

У меня есть 2 списка. 1 из них находится в неповторяющейся части формы (Schalen), другая (VraagType) находится внутри повторяющейся части.

для Schalen все работает нормально. Я открываю окно редактирования, и все поля заполняются так, как должно быть. значение Vrbl_Titel имеет значение, а раскрывающийся список Sch_ID содержит значение, полученное от объекта, который я отправил с представлением, полученным из БД.

Проблема заключается в повторяющейся части. текстовое поле для модели .Vragen [i] .Evvr_Vraag получает его значение и раскрывающийся список для модели. объект. он сохраняет стандартное значение по умолчанию, которое является первым элементом в списке выбора

как мне получить мою ценность из моего объекта 'Vragen' в выпадающий список. если я положу значение в простом текстовом поле

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

тогда текстовое поле получает значение. так что проблема в том, что выпадающее значение не изменяется из-за своего начального значения ... ошибка в MVC?

просто для информации, вот как выглядит объект (ы), отправленные в представление:

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

1 Ответ

14 голосов
/ 20 августа 2010

Кажется, что это действительно ошибка или, по крайней мере, несоответствие в ASP.NET MVC 2. Я проверил его источник и обнаружил, что метод InputHelper (), вызванный из помощника TextBoxFor (), получает значение по умолчанию, рассчитанное с

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

Но метод SelectInternal (), вызываемый из помощника DropDownListFor (), получает только имя элемента управления, найденного с помощью метода ExpressionHelper.GetExpressionText ().

Таким образом, SelectInternal () пытается найти значение по умолчанию, используя метод ViewData.Eval () из MVC 1. Известно, что этот метод не может извлечь значения из массивов по числовому индексу.

Так в вашем случае применимы

<%: 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 < fevb.Vragen.Count(); i++)
    ModelState.Add("Vragen[" + i + "].Evvr_Type", new ModelState
    {
        Value = new ValueProviderResult(fevb.Vragen[i].Evvr_Type, null, 
            CultureInfo.CurrentCulture) 
    });

Это будет сделано самим MVC после публикации, поэтому вы должны делать это вручную только в первый раз.

Второй . Вместо

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

использование

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

ViewData ["vraagtype"] в этом случае не обязательно должен содержать объекты SelectListItem, достаточно любого IEnumerable. Вы можете проверить описание метода SelectList () в случае необходимости.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...