ASP.NET MVC Общие шаблоны и коллекции - PullRequest
2 голосов
/ 25 сентября 2010

Можно ли применить атрибут к коллекции, а затем обнаружить его при переборе элементов коллекции, используя ViewData.ModelMetadata.Properties?

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

(см. сообщение Брэда Уилсона для справки об этом общем шаблонном подходе)

Например:

public class Parent
{
   [SomeAttributeIWantToDetect]        
   public IList<Child> Children{ get; set; }
}


public class Child
{
    public string Name { get; set; }
    public string Details { get; set; }
}

object.ascx: (Обратите внимание, этот код принадлежит команде ASP.NET MVC, а не моей)

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<% if (Model == null) { %>
    <%= ViewData.ModelMetadata.NullDisplayText %>
<% } else { %>
    <table cellpadding="0" cellspacing="0" border="0">
    <% foreach (var prop in ViewData.ModelMetadata.Properties.Where(pm => pm.ShowForDisplay && !ViewData.TemplateInfo.Visited(pm))) { %>
        <% if (prop.HideSurroundingHtml) { %>
            <%= Html.Display(prop.PropertyName) %>
        <% } else { %>
            <tr>
                <td>
                    <div class="display-label" style="text-align: right;">
                        <%= prop.GetDisplayName() %>
                    </div>
                </td>
                <td>
                    <div class="display-field">
                    <!-- *********** HERE ***************-->
                    <% if (prop.AdditionalValues.ContainsKey(SomeAttributeIWantToDetectAttribute)) 
                        //Do something else.....
                        else
                     %>
                        <%= Html.Display(prop.PropertyName) %>
                    <% } %>
                    </div>
                </td>
            </tr>
        <% } %>
    <% } %>
    </table>
<% } %>

Ответы [ 4 ]

1 голос
/ 29 сентября 2010

Вы несколько раз связывали http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-4-custom-object-templates.html с комментарием "Я не могу использовать ViewModels, потому что это универсальный шаблон".

Я не понимаю, почему вы в это верите. TFD и Райан понимают это правильно. Создайте две разные модели ViewModel, чтобы обернуть вашу модель, и поместите атрибуты ScaffoldColumn в модель ViewModel (или, лучше, пропустите эти поля полностью).

Object.ascx затем обнаруживает атрибут (или, конечно, наличие или отсутствие поля) в вашей ViewModel и отображает (или не отображает) поле соответствующим образом.

На самом деле, автор поста, на который вы ссылаетесь, предлагает сделать именно это: -

http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-4-custom-object-templates.html#comment-6a00e54fbd8c4988340120a6396c7a970b

"Лично моя рекомендация для люди, которые хотят строгий SoC (как и я) это использовать ViewModels и только место аннотации на представлении модели. Есть и другие проблемы с напрямую модель привязки к таким вещам, как LINQ для SQL или LINQ to Entities (например, если вы не будете осторожны, вы можете уничтожить ваши ассоциации или случайно плохой парень связывает данные во что-то это не было изначально показано в редактор), так я вообще всегда в любом случае рекомендую просматривать модели. "

Итак: -

public class Parent
{
  public IList<Child> Children{ get; set; }
}

public class Child
{
  public String Name { get; set; }
  public String Details { get; set; }
}

// Pass this one to your "Admin" view.
public class ParentAdminViewModel
{
  private Parent _parent;
  public ParentAdminViewModel(Parent parent) { this._parent = parent; }

  public IEnumerable<Child> Children
  {
    get
    {
      return _parent.Children.Select(x => new ChildAdminViewModel(x));
    }
  }
}

public class ChildAdminViewModel
{
  private Child _child;
  public ChildAdminViewModel(Child child) { this._child = child; }

  public String Name { get { return _child.Name; } }
  public String Details { get { return _child.Details; } }
}

// Pass this one to your "User" view.
public class ParentUserViewModel
{
  private Parent _parent;
  public ParentUserViewModel(Parent parent) { this._parent = parent; }

  public IEnumerable<Child> Children
  {
    get
    {
      return _parent.Children.Select(x => new ChildUserViewModel(x));
    }
  }
}

public class ChildUserViewModel
{
  private Child _child;
  public ChildAdminViewModel(Child child) { this._child = child; }

  public String Name { get { return _child.Name; } }
  // ChildUserViewModel doesn't have a Details property,
  // so Object.ascx won't render a field for it.
}

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

1 голос
/ 28 сентября 2010

Это не MVC, это ближе к классическим шаблонам ASP

Выберите, в каком лагере вы хотите находиться, и оставайтесь там

Чтобы использовать MVC, вам нужно создать ViewModel, которая выражаетМодель с точки зрения конкретного назначения рендеринга

Ваш ViewModel должен быть построен с использованием только логических команд сверху.то есть

if (Model == null)
{
  x = ViewData.ModelMetadata.NullDisplayText
}
else
{
  foreach (var prop in ViewData.ModelMetadata.Properties.Where(pm => pm.ShowForDisplay && !ViewData.TemplateInfo.Visited(pm)))
  {
    if (prop.HideSurroundingHtml)
    {
      x.Items1.Add(prop.PropertyName));
    }
    else
    {
      prop.GetDisplayName()
      if (prop.AdditionalValues.ContainsKey(SomeAttributeIWantToDetectAttribute)) 
      {
        x.Items2.Add( { Text = prop.zzz, Highlight = true} ));
      }
      else
      {
        x.Items2.Add( { Text = prop.PropertyName } ));
      }
    }
  }
}

Код выше, очевидно, неверен, я просто пытаюсь показать, что вы должны взять сложный код и логику и использовать его для построения ViewModel, он никогда не должен быть в представлении

ViewModel имеет простую конструкцию, относящуюся к используемой вами технологии рендеринга (например, атрибуты html и т. Д.)

Представление должно просто содержать простые итераторы и селекторы макетов, передаваемые из ViewModel, а не фактическую модель

1 голос
/ 28 сентября 2010

@ UpTheCreek, вы сталкиваетесь с ужасной конфронтацией за то, что хотите, чтобы люди вам помогали, но я все равно дам свои 2 цента.

Насколько я понимаю, вы хотите иметь на модели дочернюю коллекцию. В дочерней модели вы собираетесь включить некоторые атрибуты [ScaffoldColumn ("false")], но вы также хотите иметь возможность поместить атрибут в родительскую модель, который заставит средство визуализации игнорировать атрибуты ScaffoldColumn и просто показать все. Если мое понимание верно, я думаю, вы поступаете неправильно. Вы должны создавать отдельные модели представлений для случаев, когда вы хотите, чтобы отображались разные свойства.

Кроме того, я совершенно ясно, если это ваше намерение, потому что в вашем примере кода вы бы скрывали только поле ввода, а не сам ярлык. Возможно, вы пытаетесь заметить, что поле скрыто?

0 голосов
/ 26 сентября 2010

Не могли бы вы использовать отражение так: http://msdn.microsoft.com/en-us/library/z919e8tw.aspx?

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