MVC2 - Как получить родительскую модель (контейнер) внутри шаблона

StackOverflow https://stackoverflow.com/questions/4009129

Вопрос

Я пишу приложение MVC2 с использованием дантантотанов. У меня есть следующая модель:

public class FooModel 
{
    [ScaffoldColumn("false")]
    public long FooId { get; set; }

    [UIHint("BarTemplate")]
    public DateTime? Bar { get; set;}
}

Я хочу создать пользовательский шаблон отображения для бара. Я создал следующий шаблон:

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

<div class="display-label">
    <span><%: Html.LabelForModel() %></span>
</div>
<div class="display-field">
    <span><%: Html.DisplayForModel()%></span>
    <%: Html.ActionLink("Some link", "Action", new { id = ??FooId?? }) %>
</div>

Теперь моя проблема в том, что Внутренний шаблон для бара, который я хочу получить доступ к другой недвижимости от моей модели. Отказ Я не хочу создавать отдельный шаблон для Feomodel, потому что, чем мне придется жесткодей всем остальным свойствам Foomodel.

После краткого расследования с отладчиком я вижу, что:

  1. this.ViewData.ModelMetadata.ContainerTypeявляется FooModel (как и ожидалось)
  2. this.ViewData.TemplateInfo имеет непубличное недвижимость VisitedObjects(типаSystem.Collections.Generic.HashSet<object>) который содержит два элемента:FooModel а также DateTime?.

Как я могу получить доступ к моей Foomodel? Я не хочу взломать путь, используя отражение.

Обновлять:

Я принял ответ MOOTINATOR, так как он смотрит на меня как лучшее решение, которое позволяет безопасному. Я также усваивал ответ TX3, так как ответ Meootinator опирается на него. Тем не менее, я думаю, что должна быть лучшая поддержка форма MVC в таких сценариях, которые, по я считаю, довольно распространены в реальном мире, но отсутствуют в образцах приложений.

Это было полезно?

Решение

Извините, если это предложение кажется домодуемым, я не пробовал, но не мог ли вы сделать то, что предложил TX3 без необходимости создавать кучу новых классов, определив универсальный класс для ссылки на любой тип родителя, который вы хотите?

    public class FooModel 
    {
        [ScaffoldColumn("false")]
        public long FooId { get; set; }

        [UIHint("BarTemplate")]
        public ParentedDateTime<FooModel> Bar { get; set;}

        public FooModel()
        {
            Bar = new ParentedDateTime<FooModel>(this);
        }
    }


    public class ParentedDateTime<T>
    {
        public T Parent {get; set;}
        public DateTime? Babar {get; set; }

        public ParentedDateTime(T parent)
        {
            Parent = parent;
        }

}

Вы можете расширить это, чтобы инкапсулировать любой старый тип с <Parent, Child> Напечатал общий даже.

Это также даст вам преимущество, что ваш сильно напечатанный шаблон будет для

Inherits="System.Web.Mvc.ViewUserControl<ParentedDateTime<FooType>> Таким образом, вам не пришлось бы назвать откровенность, который шаблон использовать где угодно. Это больше того, как вещи предназначены для работы.

Другие советы

Может быть, вы можете создать новый класс, давайте скажем, userDateTime, и он будет содержать нумеры для нужного dateTime и остальной части необходимой информации. Затем вы будете использовать пользовательский шаблон отображения для userDateTime и получите доступ к вам информации.

Я понимаю, что вы сможете искать другое вида решения.

Я думаю, вам может быть лучше извлекать эту функциональность к вызовам HTMLHELPER от родительского вида.

Что-то типа RenderSpecialDateTime<TModel>(this HtmlHelper html, Expression<Func<TModel,DateTime?>> getPropertyExpression) вероятно, сделает работу.

В противном случае вам придется сделать что-то вроде того, что предлагается TX3. Я усваивал его ответ, но опубликовал это как альтернативу.

Разве вы не могли бы вы использовать объект словаря ViewData в контроллере, а затем захватить, что в ViewsUserControl? Это не было бы сильно напечатано, но ... Вы можете написать помощник ничего не делать, если он пуст, и ссылается, чтобы сказать, что пример истории входа в систему, если она имела значение.

Появилось бы, что где-то между MVC 5,0 и 5.2.2 в классе ModelMetAdata добавляли «контейнер».

Однако, поскольку все методы в провайдере, ответственном за создание метаданных (GetMetAdataForProperty, создание и т. Д.) У нее нет контейнера в их подписи, контейнерное свойство присваивается только в определенных случаях (GetmetAdataTaTaTaTaTaSataForProperties и GetmetAdatafromProvider в соответствии с отраженным кодом) и в моем случае обычно был нулевым.

Итак, что я закончил, - это переопределяет GetmetAdataforProperty в новом провайдере метаданных и настроить его там:

public override ModelMetadata GetMetadataForProperty(Func<object> modelAccessor, Type containerType, string propertyName)
{
  var propMetaData = base.GetMetadataForProperty(modelAccessor, containerType, propertyName);
  Object container = modelAccessor.Target.GetType().GetField("container").GetValue(modelAccessor.Target);
  propMetaData.Container = container;
  return propMetaData;
}

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top