ViewModel Свойство IEnum <> возвращает ноль (без привязки), когда содержится в частичном представлении? - PullRequest
1 голос
/ 29 марта 2012

У меня есть ViewModel, которая содержит тип Product и тип IEnumerable . У меня есть одно основное представление, которое отображает ViewModel.Product в верхней части страницы, но затем у меня есть частичное представление, которое отображает данные ViewModel.IEnumerable . На посту объект продукта первого уровня возвращается в привязке из ViweModel, тогда как ViewModel.IEnumerable возвращается в ноль.

Конечно, если я удаляю частичное представление и перемещаю представление IEnumerable в главное представление, содержимое возвращается в связанном порядке. Однако мне нужно поместить эти перечисляемые элементы в частичное представление, потому что я планирую динамически обновлять содержимое с помощью Ajax.

Почему свойство IEnumerable не связывается, когда оно помещается в частичное представление? Thx!

Модель:

public class Product
{
    public int ID { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}

public class ProductIndexViewModel
{
    public Product NewProduct { get; set; }
    public List<Product> Products { get; set; }
}

public class BoringStoreContext
{
    public BoringStoreContext()
    {
        Products = new List<Product>();
        Products.Add(new Product() { ID = 1, Name = "Sure", Price = (decimal)(1.10) });
        Products.Add(new Product() { ID = 2, Name = "Sure2", Price = (decimal)(2.10) });
    }
    public List<Product> Products { get; set; }
}

Просмотров: 1010 * *

Основной index.cshtml:

@model ViewModelBinding.Models.ProductIndexViewModel

@using (@Html.BeginForm())
{
<div>
    @Html.LabelFor(model => model.NewProduct.Name)
    @Html.EditorFor(model => model.NewProduct.Name)
</div>
<div>
    @Html.LabelFor(model => model.NewProduct.Price)
    @Html.EditorFor(model => model.NewProduct.Price)
</div>

@Html.Partial("_Product", Model.Products)

<div>
    <input type="submit" value="Add Product" />
</div>
}

Parial View _Product.cshtml:

@model List<ViewModelBinding.Models.Product>

@for (int count = 0; count < Model.Count; count++)
{ 
    <div>
    @Html.LabelFor(model => model[count].ID)
    @Html.EditorFor(model => model[count].ID)
    </div>
    <div>
    @Html.LabelFor(model => model[count].Name)
    @Html.EditorFor(model => model[count].Name)
    </div>
    <div>
    @Html.LabelFor(model => model[count].Price)
    @Html.EditorFor(model => model[count].Price)
    </div>
}

Контроллер:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        BoringStoreContext db = new BoringStoreContext();
        ProductIndexViewModel viewModel = new ProductIndexViewModel
        {
            NewProduct = new Product(),
            Products = db.Products
        };
        return View(viewModel);
    }

    [HttpPost]
    public ActionResult Index(ProductIndexViewModel viewModel)
    {
        // work with view model

        return View();
    }

} * * тысяча двадцать-один

1 Ответ

1 голос
/ 29 марта 2012

Когда вы используете @Html.Partial("_Product", Model.Products) ваши поля ввода не имеют правильных имен. Например вместо:

<input type="text" name="Products[0].ID" />

вы получите:

<input type="text" name="[0].ID" />

Просто посмотрите на созданную вами разметку, и вы увидите проблему. Это связано с тем, что при использовании Html.Partial навигационный контекст не сохраняется. Имена полей ввода не имеют префикса имени коллекции - Products и, как следствие, механизм связывания модели не может связать его правильно. Взгляните на следующую запись в блоге , чтобы лучше понять ожидаемый формат передачи.

Я бы порекомендовал вам использовать шаблоны редакторов, которые сохраняют контекст. Так что вместо:

@Html.Partial("_Product", Model.Products)

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

@Html.EditorFor(x => x.Products)

и теперь переместите шаблон _Product.cshtml на ~/Views/Shared/EditorTemplates/Product.cshtml. Кроме того, поскольку шаблон редактора автоматически распознает, что свойство Products имеет значение IEnumerable<T>, он будет отображать шаблон для каждого элемента этой коллекции. Таким образом, ваш шаблон должен быть строго типизирован для одного продукта, и вы можете избавиться от цикла:

@model Product
<div>
    @Html.LabelFor(model => model.ID)
    @Html.EditorFor(model => model.ID)
</div>
<div>
    @Html.LabelFor(model => model.Name)
    @Html.EditorFor(model => model.Name)
</div>
<div>
    @Html.LabelFor(model => model.Price)
    @Html.EditorFor(model => model.Price)
</div>

Теперь все работает по соглашению и будет правильно связываться.

...