我们有一堆域实体应该呈现为html格式,在弹出窗口中显示它们的详细信息。
我很乐意做这样的事情:
Product product = new Product(...);
product.ToHtml(); // or: HtmlRenderer.Render(Product);
但我的主要问题是如何从后面做这些事情。 我有3个不同的答案:
1。按代码渲染:
我可以简单地编写用于在ToHtml方法(C#)中呈现Html的代码 - 问题在于它太静态。如果你想将标题移动到中间,你应该改变代码。 而且,在C#中读取Html缩进非常困难。
2。使用XSL:
XSL文件可以轻松管理Html模板并使用XSLT我可以将XML文件转换到文档的正确位置。 解析器已经由别人编写(只需要学习语法) **为此,我们需要每个对象都可以序列化为Xml。如果对象发生了变化 - > Xml将被更改 - > xslt也需要改变 **这也可以让我选择简单地缩进html例如:添加css功能和\或更改html设计
第3。使用其他模板引擎:
写我自己的C# - > Html模板引擎,因此它将从文件(* .template)中读取模板,并使用反射将正确的属性插入模板的正确位置。 **在这个解决方案中,我们可以考虑许多问题,例如:语法应该如何? 这件事好吗? %名称%%说明% 以及我们如何处理数组? **也许我们可以使用现有的引擎(Brail或T4-Templating)?
你更喜欢什么? 你知道一个好引擎吗? 现在我更喜欢第二种解决方案,但它会很慢。
感谢
答案 0 :(得分:5)
我曾经需要将任何类型的集合呈现给Html表。我在IEnumerable< T>上创建了一个扩展方法。有css等过载。你可以在这里看到我的博客文章:
http://crazorsharp.blogspot.com/2009/03/cool-ienumberable-extension-method_25.html
它使用反射来获取对象的所有属性,并呈现一个漂亮的小表。看看这对你有用。
[System.Runtime.CompilerServices.Extension()]
public string ToHtmlTable<T>(IEnumerable<T> list, string propertiesToIncludeAsColumns = "")
{
return ToHtmlTable(list, string.Empty, string.Empty, string.Empty, string.Empty, propertiesToIncludeAsColumns);
}
[System.Runtime.CompilerServices.Extension()]
public string ToHtmlTable<T>(IEnumerable<T> list, string tableSyle, string headerStyle, string rowStyle, string alternateRowStyle, string propertiesToIncludeAsColumns = "")
{
dynamic result = new StringBuilder();
if (String.IsNullOrEmpty(tableSyle)) {
result.Append("<table id=\"" + typeof(T).Name + "Table\">");
} else {
result.Append((Convert.ToString("<table id=\"" + typeof(T).Name + "Table\" class=\"") + tableSyle) + "\">");
}
dynamic propertyArray = typeof(T).GetProperties();
foreach (object prop in propertyArray) {
if (string.IsNullOrEmpty(propertiesToIncludeAsColumns) || propertiesToIncludeAsColumns.Contains(prop.Name + ",")) {
if (String.IsNullOrEmpty(headerStyle)) {
result.AppendFormat("<th>{0}</th>", prop.Name);
} else {
result.AppendFormat("<th class=\"{0}\">{1}</th>", headerStyle, prop.Name);
}
}
}
for (int i = 0; i <= list.Count() - 1; i++) {
if (!String.IsNullOrEmpty(rowStyle) && !String.IsNullOrEmpty(alternateRowStyle)) {
result.AppendFormat("<tr class=\"{0}\">", i % 2 == 0 ? rowStyle : alternateRowStyle);
} else {
result.AppendFormat("<tr>");
}
foreach (object prop in propertyArray) {
if (string.IsNullOrEmpty(propertiesToIncludeAsColumns) || propertiesToIncludeAsColumns.Contains(prop.Name + ",")) {
object value = prop.GetValue(list.ElementAt(i), null);
result.AppendFormat("<td>{0}</td>", value ?? String.Empty);
}
}
result.AppendLine("</tr>");
}
result.Append("</table>");
return result.ToString();
}
答案 1 :(得分:3)
这是您视图的工作,而不是您的控制器或模型。正如您所怀疑的那样,使用方法(1)会使您的更改变得非常脆弱。相反,为您想要呈现特定域实体的每种方式编写视图片段。然后只需拉入相应的视图即可构建最终页面。
答案 2 :(得分:3)
我对John Feminella表示赞同。将Html渲染直接集成到您的域实体中是对您的域的可怕污染,具有完全随意和外部的关注。就像约翰所说,通过这样做,你将使你的实体变得非常脆弱,并打破这两个关键规则:分离关注和单一责任。
根据您提供的选择,#3最接近合适的方式。您无需编写自己的模板引擎。网上有大量免费和现成的模板引擎,可以完成更多的工作(NVelocity,StringTemplate,Brail等等)
在您的演示文稿/视图中继续渲染它所属的位置,并且不要在更高级别的问题上污染您的域名。
答案 3 :(得分:2)
我真的更喜欢方法A. HTML已经是一个标准,所以你不应该用XML等中间格式(通过XSL - 方法2)或自定义格式(方法3)打败自己。
如果在/为ASP.NET MVC编写,你可以构建一个.ASCX(用户控件)来接受你的类型的对象并呈现适当的HTML。而且你没有得到令人讨厌的C#缩进,没有突出显示也没有自动完成。
您还可以编写多个用户视图以适应一种对象类型的不同方案。
答案 4 :(得分:1)
经过一番研究后,我创建了自己的函数将Any Object转换为HTMLString。
VB .Net代码:
Public Function ToHtmlString(ByVal fObj As Object) As String
Dim pType = fObj.GetType()
Dim props As IList(Of PropertyInfo) = pType.GetProperties()
Dim value As Object = Nothing
Dim htmlString As String = "<html><body><form>"
For Each p In props
value = p.GetValue(fObj, Nothing)
If value <> Nothing Then
htmlString += String.Format("<input type=""hidden"" name=""{0}"" id=""{0}"" value=""{1}""/>", p.Name, value)
End If
Next
htmlString += "</form></body></html>"
Return htmlString.ToString()
它将从特定对象获取属性名称和值。你可以根据你的
来操纵HTML答案 5 :(得分:0)
您是否有理由不想创建自定义控件.ascx文件,该文件将域实体对象作为参数,然后您可以以任何方式创建gui。这样,您可以动态地将控件添加到页面,只需设置一个属性来填充它们。
编辑1: 只需将控件呈现给HTMLTextWriter,而不是将其放在页面上。
StringBuilder outString = new StringBuilder();
StringWriter outWriter = new StringWriter(outString);
HtmlTextWriter htmlText = new HtmlTextWriter(outWriter);
System.Web.UI.WebControls.Label lbl1 = new System.Web.UI.WebControls.Label();
lbl1.Text = "This is just a test!";
lbl1.ToolTip = "Really";
lbl1.RenderControl(htmlText);
ViewData["Output"] = outString.ToString();
输出
<span title="Really">This is just a test!</span>
当然使用自定义控件而不是内置控件,但这是一个快速简单的演示。
答案 6 :(得分:0)
就个人而言,我将第二种方法和第三种方法结合起来:只需使用反射创建一个通用的XML文档,比如说:
<object type="xxxx">
<property name="ttt" value="vvv"/>
...
</object>
并使用XSTL样式表从中创建实际的HTML。