确定,
我有一个使用实体框架的新MVC项目。我正在吐出消息(这是一个公告板样式部分),现在根据一些条件因素,表输出中的行必须具有不同的类样式。
从控制器传递到页面的模型是实体模型(称为消息并包含与数据库相同的字段)
现在,为了获得行样式,我做了以下内容,
<%
int i = 0;
foreach (var message in ViewData.Model.MessageList)
{
string className = "rowEven";
if (i % 2 == 0) { className = "rowOdd"; }
if (message.Deleted) { className = "deleted"; }
if (message.AuthorisedBy == null) { className = "notAuth"; }
if (message.Deleted) { className = "deleted"; }
%>
<tr class="<%=className%>">
<td><%= Html.CheckBox("mc1")%></td>
<td>
<%= Html.ActionLink(message.Title, "Details", new { id = message.MessageID })%>
</td>
<td>User Name Here</td>
<td><%= Html.Encode(message.PublishDateTime.ToString())%></td>
</tr>
<%
i++;
}
%>
哪个非常难看,必须有更好的方法来做这个,有什么建议吗?
答案 0 :(得分:5)
这绝对是表示逻辑,视图属于它。但是,您最好将CSS类选择代码移动到视图助手,它将同时接受Message
和MessageList
:
public static string GetMessageCssClassName(this /* Don't remember :) */, Message message, MessageList messages)
{
var cssClassName = messages.IndexOf(message) % 2 == 0 ?
"rowOdd" : "rowEven";
if(message.Deleted) cssClassName = "deleted";
if(message.AuthorisedBy == null) cssClassName = "notAuth";
if(message.Deleted) cssClassName = "deleted";
}
现在你可以在你的<tr class="Html.GetMessageCssClassName(...)">
中调用它,摆脱i
计数器:
<% foreach (var message in ViewData.Model.MessageList) { %>
<tr class="<%= Html.GetMessageCssClassName(message, ViewData.Model.MessageList) %>">
<td><%= Html.CheckBox("mc1")%></td>
<td>
<! -- Remaining stuff here -->
<% } %>
答案 1 :(得分:2)
我建议在这里使用model-view-viewmodel。这允许您将大量逻辑封装在视图模型类中,然后只需在视图模型上调用方法,而不是将逻辑内联。这会让它看起来像这样......
<% foreach (var messageViewModel in ViewData.Model.MessageList) { %>
<tr class="<%=message.RowClass%>">
<td><%= Html.CheckBox("mc1")%></td>
<td>
<%= Html.ActionLink(message.Title, "Details", new { id = message.MessageID })%>
</td>
<td>User Name Here</td>
<td><%= Html.Encode(message.PublishedAt)%></td>
</tr>
<% } %>
虽然您最终会获得更多类,但您可以获得更多可读标记,并且您的应用程序更易于测试。它将您的视图转换为视图模型上的一个非常简单的窗口。然后,视图模型封装了视图所需的任何逻辑和属性。
回复您的评论here是一篇文章,介绍MVC中的模型 - 视图 - 视图模型模式。您只需要创建一个包含一堆属性和/或方法的类,并使用您需要的所有内容填充此类。然后将类传递给您的视图,而不是直接传递模型。您甚至可以使用AutoMapper或其他映射框架自动将模型映射到视图模型。
答案 2 :(得分:1)
添加一些辅助方法怎么样?您可以将自己的扩展方法编写到基础HtmlHelper类中,这样就可以编写类似:
的内容...
<tr class="<%= Html.GetMessageCssClass(i, message) %>">
...
答案 3 :(得分:0)
正如很多人已经提到过的,你可以为你的Namespace.Site项目(mvc项目)中的Message
类编写一个扩展方法。
类似的东西:
public static class Extensions
{
public static string CssClass(this Message message,int counter)
{
if (i % 2 == 0)
return "rowOdd";
else if (message.AuthorisedBy == null)
return "notAuth";
else if (message.Deleted)
return "deleted";
return "rowEven";
}
}
用法:
<tr class="<%=message.CssClass(i)%>">
<td><%= Html.CheckBox("mc1")%></td>
<td><%= Html.ActionLink(message.Title, "Details", new { id = message.MessageID })%></td>
<td>User Name Here</td>
<td><%= Html.Encode(message.PublishDateTime.ToString())%></td>
</tr>