Представьте себе обычный сценарий, это более простой вариант, что я'м иду через. Я на самом деле есть несколько слоев дальнейшего раскроя на шахте....
Но это сценарий
Тема содержит список<рубрика> Категория содержит список<продукт> Продукт содержит список<заказа>
Мой контроллер обеспечивает полностью заполнен тему, со всеми категориями на эту тему, на товары этой категории, а их заказы.
Сбор заказов имеет свойство количество (среди многих других), который должен быть редактируемым.
@model ViewModels.MyViewModels.Theme
@Html.LabelFor(Model.Theme.name)
@foreach (var category in Model.Theme)
{
@Html.LabelFor(category.name)
@foreach(var product in theme.Products)
{
@Html.LabelFor(product.name)
@foreach(var order in product.Orders)
{
@Html.TextBoxFor(order.Quantity)
@Html.TextAreaFor(order.Note)
@Html.EditorFor(order.DateRequestedDeliveryFor)
}
}
}
Если я вместо того, чтобы использовать лямбда-тогда я, кажется, только чтобы получить ссылку на топ-модель объекта, то "Тема" и не те, в цикле foreach.
То, что я'м пытаюсь сделать, там даже возможности нет или я переоценил и понял, что это возможно?
С выше я получаю сообщение об ошибке на TextboxFor, В и т. д.
CS0411: тип аргументов для метода 'System.Web.Mvc.Html.InputExtensions.TextBoxFor<TModel,TProperty>(System.Web.Mvc.HtmlHelper
, система.В LINQ.Выражения.Выражение<система.Функ<модели tmodel,TProperty>>)' не может быть выведено из использования. Попробуйте указать аргументы типа > в явном виде.
Спасибо.
Быстрый ответ, чтобы использовать цикл for()вместо
еогеасп()` петли. Что-то вроде:
@for(var themeIndex = 0; themeIndex < Model.Theme.Count(); themeIndex++)
{
@Html.LabelFor(model => model.Theme[themeIndex])
@for(var productIndex=0; productIndex < Model.Theme[themeIndex].Products.Count(); productIndex++)
{
@Html.LabelFor(model=>model.Theme[themeIndex].Products[productIndex].name)
@for(var orderIndex=0; orderIndex < Model.Theme[themeIndex].Products[productIndex].Orders; orderIndex++)
{
@Html.TextBoxFor(model => model.Theme[themeIndex].Products[productIndex].Orders[orderIndex].Quantity)
@Html.TextAreaFor(model => model.Theme[themeIndex].Products[productIndex].Orders[orderIndex].Note)
@Html.EditorFor(model => model.Theme[themeIndex].Products[productIndex].Orders[orderIndex].DateRequestedDeliveryFor)
}
}
}
Но это заминалось почему это решает проблему. Есть три вещи, которые у вас есть по меньшей мере, поверхностного понимания, прежде чем вы сможете решить эту проблему. Я признать, что я карго-культовых это в течение длительного времени, когда я начал работать с рамками. И это заняло у меня довольно долгое время чтобы действительно узнать, что происходит. Эти три вещи:
LabelFor
и другие ...для
помощники работают в MVC? LabelFor
и другие ...для
помощники работают в MVC? Так, вы'вэ используется HtmlHelper<П>расширения
LabelFor " и " TextBoxFor и другим, и
вы, наверное, замечали, что когда вы взываете к ним, они не лямбда и то волшебным создает
некоторые HTML. Но как?
Итак, первое, что хочу отметить, это подпись на этих помощников. Давайте посмотрим на самый простой перегрузки
TextBoxFor
public static MvcHtmlString TextBoxFor<TModel, TProperty>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expression
)
Во-первых, это метод расширения для строго типизированного HtmlHelper
, типа <модели tmodel>
. Так, просто
что происходит за кулисами, когда бритва представляет этот вид формирует класс.
Внутри этого класса является экземпляром HtmlHelper<модели tmodel>
(как свойство HTML-код
, который является, почему вы можете использовать @HTML-код...
),
где модели tmodel-это тип, определенный в заявлении вашему @модель
. Так что в вашем случае, когда вы смотрите на модели tmodel этот вид ` всегда будет просмотр моделей типа
.MyViewModels.Тема`.
Теперь, следующий аргумент-это немного сложнее. Так давайте посмотрим на вызов
@Html.TextBoxFor(model=>model.SomeProperty);
кнопку func<модели tmodel, TProperty>
, где модели tmodel
является типом модели представления и TProperty
выводится как тип свойства.
Но это не совсем верно, если вы посмотрите на реальных тип аргумента свое выражение<изм<модели tmodel, TProperty>>. Поэтому, когда вы обычно генерируют лямбда-выражения, компилятор берет и лямбда компилируется в MSIL-код, как и любой другой функции (который является, почему вы можете использовать делегаты, метод группировок, и лямбда-выражения более или менее взаимозаменяемо, потому что они просто ссылки на код.) Однако, когда компилятор видит, что тип-это
выражение<> это не'т сразу компилирует лямбда-вниз в MSIL, а не создает
Дерево Выражения!
Что такое дерево выражения? кнопку func<>
или действие на< и GT;
, как только вы их, они в значительной степени атомных. Все, что вы можете реально сделать, это вызвать()
их, или сказать им, чтобы
делать ту работу, которую они должны делать.
`Выражение<изм<>> с другой стороны, представляет собой коллекция действий, которые могут быть добавлены, манипулировать, посетил, или составлено и вызывается.
Так почему ты говоришь мне все это? Так что понимание того, что для себя выражение<> мы можем вернуться в формат HTML.TextBoxFor. При отображении текстового поля, он должен для создания нескольких вещей *о* имущество, которое вы ему даете. Такие вещи, как "атрибуты" на имущество, для проверки, и конкретно в этом случае он должен выяснить, что с *имя* в
<ввод> тег.
Она делает это путем назальный ходьбе; дерево выражения и построения имени. Так что за такое выражение как модель=>модель.SomeProperty
, он ходит выражение
сбор свойства, которые вы просите и строит <имя Входа='SomeProperty'>
.
Более сложный пример, как модель=>модель.Фу.Баре.Баз.Так: foobar, он может генерировать в
<input имя="и Фу.Баре.Баз.Фрагментик" в значении" и[все это фрагментик] и" /> Смысл? Это не просто работа
кнопку func<>`, но как она делает свою работу-это важно.
(Примечание другие фреймворки, такие как LINQ в SQL делать подобные вещи, идя дерева выражений и построение различных грамматических, что в этом случае SQL-запрос)
Поэтому, как только вы получаете это, мы должны кратко рассказать о модели связующего. Когда форма будет размещена, это's просто как плоская
Словарь<строку, строку>
мы потеряли иерархическую структуру вложенных наш вид модели может иметь. Это'ы
модель Биндер'ы работу, чтобы занять этот ключ-значение пары комбо и попытка воссоздания объекта с некоторыми свойствами. Как это сделать
это? Как вы уже догадались, с помощью "по ключ" или название входные данные, которые были выложены.
Так что если форма столба выглядит
Foo.Bar.Baz.FooBar = Hello
SomeViewModel
, то он делает противоположное тому, что помощник сделал в первую очередь. Он ищет
свойство называется "фу" и. Потом он смотрит на собственность называемые "баре" рядом с "фу" и он ищет себе "баз" и... и так далее...
Наконец, он пытается проанализировать ценность в типа "с программой" и назначить его, чтобы "программой" по.
Фух!!!
И вуаля, у вас есть свои модели. Экземпляр модели Биндер просто построены выдается на запрашиваемое действие. Поэтому ваше решение не't работа потому что в HTML.[Тип]для прислуги () нужно выражение. И вы не просто давая им значение. Он понятия не имеет
каков контекст для этого значения, и он не'т знаю, что делать с ним.
Сейчас некоторые люди предложили использовать отпечатки для визуализации. Теперь это в теории будет работать, но возможно не так, как вы ожидаете. Если вы предоставляете частичную, изменении типа модели tmodel
, потому что вы находитесь в другом контексте посмотреть. Это означает, что вы можете описать
вашу собственность с более коротким выражением. Это также означает, когда хелпер генерирует имя для своего выражения, она будет неглубокой. Это
будет создать только на основе выражения'ы (не весь контекст).
Предположим, у вас было частичное, что всего вынесено на "баз", которая (в нашем примере до). Внутри что частично ты мог бы просто сказать:
@Html.TextBoxFor(model=>model.FooBar)
А не
@Html.TextBoxFor(model=>model.Foo.Bar.Baz.FooBar)
Это означает, что он будет генерировать тег "input", как это:
<input name="FooBar" />
программой
с структуры tmodel
. Что в лучшем случае это'Т есть, а в худшем-совершенно другое. Если вы расклеивали на определенное действие, что прием баз
, а не корни модель, то это будет отлично работать! На самом деле, частичные-это хороший способ изменить свой контекст представления, например, если у вас страницы с несколькими формами, что все различные действия, затем делает частичный для каждого из них будет отличной идеей. Теперь как только вы получите все это, вы можете начать делать действительно интересные вещи с выражение<>
, по программно удлиняя их и делая
другие аккуратные вещи с ними. Я выиграл'т попасть ни на что. Но, надеюсь, это будет
даст вам лучшее понимание того, что происходит за кулисами и почему вещи действуют способ, которым они.
Вы можете просто использовать EditorTemplates, чтобы сделать это, вы должны создать каталог по кличке "EditorTemplates" в контроллере's посмотреть папку и поместить отдельный вид для каждого из вложенных сущностей (назван объект имя класса)
Основной вид :
@model ViewModels.MyViewModels.Theme
@Html.LabelFor(Model.Theme.name)
@Html.EditorFor(Model.Theme.Categories)
Вид, категория (/MyController/EditorTemplates/категория.cshtml) на :
@model ViewModels.MyViewModels.Category
@Html.LabelFor(Model.Name)
@Html.EditorFor(Model.Products)
Вид продукта (/MyController/EditorTemplates/продукта.cshtml) на :
@model ViewModels.MyViewModels.Product
@Html.LabelFor(Model.Name)
@Html.EditorFor(Model.Orders)
и так далее
таким образом HTML-код.Помощник в будет генерировать элемент'с именами в упорядоченном виде и поэтому вы выиграли'Т есть какие-либо проблемы для получения запостил тему образование в целом
Вы можете добавить в категорию частичное и товара частичная, каждый бы взял меньшую часть основной модели, как это'ы собственную модель, т. е. категории's модель тип может быть объект IEnumerable<категория>, можно передать в модель.Тема к нему. Продукт'с частичной может быть объект IEnumerable<продукт> что вы передаете модель.Товаров в (из категории частично).
Я'м не уверен, если это будет правильный путь, но было бы интересно узнать.
Редактировать
После отправки этого ответа, я've использовали EditorTemplates и найти этот самый простой способ справиться с повторения входных групп или товаров. Он обрабатывает все ваши проблемы проверки сообщений и форма представления/модель привязки беды автоматически.
При использовании цикла foreach в представлении для обвязана модель ... Ваша модель должна быть в списке формат.
я.е
@model IEnumerable<ViewModels.MyViewModels>
@{
if (Model.Count() > 0)
{
@Html.DisplayFor(modelItem => Model.Theme.FirstOrDefault().name)
@foreach (var theme in Model.Theme)
{
@Html.DisplayFor(modelItem => theme.name)
@foreach(var product in theme.Products)
{
@Html.DisplayFor(modelItem => product.name)
@foreach(var order in product.Orders)
{
@Html.TextBoxFor(modelItem => order.Quantity)
@Html.TextAreaFor(modelItem => order.Note)
@Html.EditorFor(modelItem => order.DateRequestedDeliveryFor)
}
}
}
}else{
<span>No Theam avaiable</span>
}
}
Это видно из ошибки.
Вспомогательные методы HTML приложения дописывается с "За" и рассчитывает лямбда-выражение в качестве параметра.
Если вы передаете значение напрямую, лучше использовать нормальный.
например
Вместо TextboxFor(....) используйте текстовое поле()
синтаксис для TextboxFor будет как HTML.TextBoxFor(м=>м. Собственность)
В вашем сценарии вы можете использовать основные для петли, так как это даст вам индекс.
@for(int i=0;i<Model.Theme.Count;i++)
{
@Html.LabelFor(m=>m.Theme[i].name)
@for(int j=0;j<Model.Theme[i].Products.Count;j++) )
{
@Html.LabelFor(m=>m.Theme[i].Products[j].name)
@for(int k=0;k<Model.Theme[i].Products[j].Orders.Count;k++)
{
@Html.TextBoxFor(m=>Model.Theme[i].Products[j].Orders[k].Quantity)
@Html.TextAreaFor(m=>Model.Theme[i].Products[j].Orders[k].Note)
@Html.EditorFor(m=>Model.Theme[i].Products[j].Orders[k].DateRequestedDeliveryFor)
}
}
}