是否可以将属性应用于集合,然后在使用ViewData.ModelMetadata.Properties
迭代集合成员时检测到此属性?
我想将一个属性应用于集合,以指定集合中的项目是否应该完整显示。我想在Object.ascx(处理未知类型的对象的显示)中检测到这一点,以决定要显示的详细程度。
(有关此通用模板方法的背景,请参阅brad wilson's post)
例如:
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>
<% } %>
答案 0 :(得分:1)
这不是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 :(得分:1)
@UpTheCreek,你因为希望别人帮助你而感觉非常具有对抗性,但无论如何我都会给你2美分。
我的理解是,您希望能够在模型上拥有子集合。在子模型上,您将包括一些[ScaffoldColumn(“false”)]属性,但您还希望能够在父模型上放置一个属性,该属性将导致渲染器忽略ScaffoldColumn属性并仅显示一切。如果我的理解是正确的,我认为你会以错误的方式解决这个问题。您应该为需要显示不同属性的情况创建单独的视图模型。
另外,我很清楚这是否是你的意图,因为在你的代码示例中你只会隐藏输入字段而不是标签本身。也许你是想试着隐藏这个领域?
答案 2 :(得分:1)
您已多次将http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-4-custom-object-templates.html与评论“我无法使用ViewModels链接,因为这是通用模板”。
我不明白你为何相信这一点。 TFD和Ryan完全正确。创建两个不同的ViewModel来包装模型,并将ScaffoldColumn属性放在ViewModel上(或者更好,完全省略这些字段)。
然后,Object.ascx会在ViewModel上检测属性(当然还有字段的存在与否),并相应地显示(或不显示)字段。
事实上,您链接的帖子的作者建议完全这样做: -
“我个人推荐 想要严格SoC的人(就像我一样) 是使用ViewModels而只放置 视图模型上的注释。 直接还有其他问题 模型绑定到LINQ to之类的东西 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.
}
如果你想编辑,显然你也需要连接setter。
答案 3 :(得分:0)