ASP.NET MVC 2 строго типизированное частичное представление для списка внешних ключей - какой тип передается? - PullRequest
0 голосов
/ 21 октября 2010

Я хотел бы передать список элементов для раскрывающегося списка в строго типизированное частичное представление. Родительское представление использует класс ViewModel, который содержит свойства как для значения, которое я хочу установить, так и для списка параметров, который должен содержать связанный раскрывающийся список.

Моя ViewModel выглядит так:

public class EntityFormViewModel
{
    private MyDBEntity Entity { get; set; }

    // *** The list of options. ***
    public SelectList DataTypeSelectList { get; private set; }

    public int EntityId { get; set; }
    public byte FormatId { get; set; }

    // *** The property the options relate to. ***
    [UIHint("DataTypesDropDownST")]
    public string DataType { get; set; }
    // Other properties snipped...


    public EntityFormViewModel(EntityModel db, int Id)
    {
        Entity = db.MyDBEntity.First(e => e.EntityId == Id);
        DataTypeSelectList = new SelectList(db.SDDS_DataType.ToList(), "DataType", "Description", this);

        EntityId = Entity.EntityId;
        FormatId = Entity.FormatId;
        DataType = Entity.DataType;
        // Etc ...
    }

    public void Update(EntityModel db)
    {
        Entity.EntityId = EntityId;
        Entity.FormatId = FormatId;
        Entity.DataType = DataType;
        // Etc ...

        db.SaveChanges();
    }
};

Мое частичное представление в EditorTemplates / DataTypesDropDown.ascx выглядит как

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MvcApp.Controllers.EntityFormViewModel>" %>

<!-- Doesn't work. -->
<%= Html.DropDownListFor(m => Model, Model.DataTypeSelectList) %>

<!-- Doesn't work either. -->
<!-- <% Html.DropDownListFor(m => Model, Model.DataTypeSelectList); %> -->

И мой родительский вид выглядит как

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MvcApp.Controllers.EntityFormViewModel>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Edit
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <h2>Edit</h2>

    <% using (Html.BeginForm()) {%>
        <%: Html.ValidationSummary(true) %>

        <fieldset>
            <legend>Fields</legend>

            <%: Html.EditorFor(m => m) %>

            <p>
                <input type="submit" value="Save" />
            </p>
        </fieldset>

    <% } %>

    <div>
        <%: Html.ActionLink("Back to List", "Index") %>
    </div>

</asp:Content>

Я могу заставить его работать нормально без строгой типизации, передав список элементов в словаре ViewData, таким образом:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>

<%: Html.DropDownList("", new SelectList(ViewData["DataTypes"] as IEnumerable, "DataType", "Description", Model)) %>

но я получаю следующую ошибку при строгой типизации:

Элемент модели, передаваемый в словарь, имеет тип 'System.String', но для этого словаря требуется элемент модели типа 'MvcApp.Controllers.EntityFormViewModel'.

Похоже, неправильный тип (строка) передается в частичное представление, но что я могу сделать, чтобы изменить тип, который я передаю? Или мой подход совершенно неверный? Если так, как это должно быть сделано? Я предполагаю, что это очень распространенный сценарий.

Я знаю, что должен использовать класс «хранилище» для доступа к базе данных, но я хочу, чтобы это сработало, прежде чем создавать вокруг него слишком много других вещей. Обратите внимание, что моя ViewModel находится в пространстве контроллеров. Думаю, мне следует переместить его в пространство имен Model, но я сомневаюсь, что это является причиной моей проблемы.

=============================================== ==================================

UPDATE

У меня все еще есть проблема, но по крайней мере я решил ошибку компилятора. Я изменил вид модели следующим образом

    // Make this private
    private string DataType { get; set; }

    // Add this which supplies all the list information.
    [UIHint("DataTypesDropDownST")]
    public DataTypeOptsAndVal DataTypeAndOpts
    {
        get { return new DataTypeOptsAndVal(DataType, DataTypeSelectList); } 
        set { DataType = value.DataType; } 
    }

Идея проистекает из того факта, что возвращаемое значение свойства контролирует тип, передаваемый в частичное представление; вся модель не пройдена, что было моей более ранней ошибкой. Поэтому я возвращаю тип, который содержит все, что нужно частичному представлению. Новый частичный вид

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MvcApp.Controllers.DataTypeOptsAndVal>" %>

<%: Html.DropDownListFor(m => m.DataType, Model.DataTypeSelectList) %>

Однако форма теперь отображается с этим полем полностью. Я попытался включить статический текст в частичное представление, но даже это не было обработано.

Любая помощь приветствуется. Конечно, не так уж сложно набрать список параметров?

Ответы [ 2 ]

0 голосов
/ 01 ноября 2010

ОК, поскольку здесь я не получил ответа, я подумал, что здесь никто не знает! Но есть ответ, и он задокументирован здесь:

http://www.dalsoft.co.uk/blog/index.php/2010/04/26/mvc-2-templates/#Complex_Types

Я был абсолютно прав, поскольку проблема заключалась в том, что стандартное сопоставление шаблона MVC поддерживает только простые типы. Однако простое решение состоит в том, чтобы просто указать, какой шаблон использовать:

<%: Html.EditorFor(m => m.DataTypeAndOpts, "DataTypesDropDownST") %>

С "DataTypesDropDownST", являющимся частичным именем представления.

Однако, почему он не работает с EditorForModel () и [UIHint], я до сих пор не знаю. (Конечно, UIHint делает то же самое, что и приведенный выше код?)

0 голосов
/ 22 октября 2010

На вашем главном экране вместо:

<%: Html.EditorFor(m => m) %>

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

<%: Html.EditorForModel() %>

Это эквивалентно, но более читабельно.

Что касается того, почему шаблон редактора не отображается, вы использовали атрибут UIHint в вашей модели. Это означает, что он будет искать ~/Views/Home/EditorTemplates/DataTypesDropDownST.ascx. Убедитесь, что этот файл находится в этом месте и содержит код, который вы указали в своем обновлении.

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