New tests.
[mono.git] / mcs / class / System.Web.Mvc2 / System.Web.Mvc / Html / DefaultDisplayTemplates.cs
1 /* ****************************************************************************\r
2  *\r
3  * Copyright (c) Microsoft Corporation. All rights reserved.\r
4  *\r
5  * This software is subject to the Microsoft Public License (Ms-PL). \r
6  * A copy of the license can be found in the license.htm file included \r
7  * in this distribution.\r
8  *\r
9  * You must not remove this notice, or any other, from this software.\r
10  *\r
11  * ***************************************************************************/\r
12 \r
13 namespace System.Web.Mvc.Html {\r
14     using System;\r
15     using System.Collections;\r
16     using System.Collections.Generic;\r
17     using System.Data;\r
18     using System.Globalization;\r
19     using System.Linq;\r
20     using System.Text;\r
21     using System.Web.Mvc.Resources;\r
22     using System.Web.UI.WebControls;\r
23 \r
24     internal static class DefaultDisplayTemplates {\r
25         internal static string BooleanTemplate(HtmlHelper html) {\r
26             bool? value = null;\r
27             if (html.ViewContext.ViewData.Model != null) {\r
28                 value = Convert.ToBoolean(html.ViewContext.ViewData.Model, CultureInfo.InvariantCulture);\r
29             }\r
30 \r
31             return html.ViewContext.ViewData.ModelMetadata.IsNullableValueType\r
32                         ? BooleanTemplateDropDownList(value)\r
33                         : BooleanTemplateCheckbox(value ?? false);\r
34         }\r
35 \r
36         private static string BooleanTemplateCheckbox(bool value) {\r
37             TagBuilder inputTag = new TagBuilder("input");\r
38             inputTag.AddCssClass("check-box");\r
39             inputTag.Attributes["disabled"] = "disabled";\r
40             inputTag.Attributes["type"] = "checkbox";\r
41             if (value) {\r
42                 inputTag.Attributes["checked"] = "checked";\r
43             }\r
44 \r
45             return inputTag.ToString(TagRenderMode.SelfClosing);\r
46         }\r
47 \r
48         private static string BooleanTemplateDropDownList(bool? value) {\r
49             StringBuilder builder = new StringBuilder();\r
50 \r
51             TagBuilder selectTag = new TagBuilder("select");\r
52             selectTag.AddCssClass("list-box");\r
53             selectTag.AddCssClass("tri-state");\r
54             selectTag.Attributes["disabled"] = "disabled";\r
55             builder.Append(selectTag.ToString(TagRenderMode.StartTag));\r
56 \r
57             foreach (SelectListItem item in DefaultEditorTemplates.TriStateValues(value)) {\r
58                 builder.Append(SelectExtensions.ListItemToOption(item));\r
59             }\r
60 \r
61             builder.Append(selectTag.ToString(TagRenderMode.EndTag));\r
62             return builder.ToString();\r
63         }\r
64 \r
65         internal static string CollectionTemplate(HtmlHelper html) {\r
66             return CollectionTemplate(html, TemplateHelpers.TemplateHelper);\r
67         }\r
68 \r
69         internal static string CollectionTemplate(HtmlHelper html, TemplateHelpers.TemplateHelperDelegate templateHelper) {\r
70             object model = html.ViewContext.ViewData.ModelMetadata.Model;\r
71             if (model == null) {\r
72                 return String.Empty;\r
73             }\r
74 \r
75             IEnumerable collection = model as IEnumerable;\r
76             if (collection == null) {\r
77                 throw new InvalidOperationException(\r
78                     String.Format(\r
79                         CultureInfo.CurrentCulture,\r
80                         MvcResources.Templates_TypeMustImplementIEnumerable,\r
81                         model.GetType().FullName\r
82                     )\r
83                 );\r
84             }\r
85 \r
86             Type typeInCollection = typeof(string);\r
87             Type genericEnumerableType = TypeHelpers.ExtractGenericInterface(collection.GetType(), typeof(IEnumerable<>));\r
88             if (genericEnumerableType != null) {\r
89                 typeInCollection = genericEnumerableType.GetGenericArguments()[0];\r
90             }\r
91             bool typeInCollectionIsNullableValueType = TypeHelpers.IsNullableValueType(typeInCollection);\r
92 \r
93             string oldPrefix = html.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix;\r
94 \r
95             try {\r
96                 html.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = String.Empty;\r
97 \r
98                 string fieldNameBase = oldPrefix;\r
99                 StringBuilder result = new StringBuilder();\r
100                 int index = 0;\r
101 \r
102                 foreach (object item in collection) {\r
103                     Type itemType = typeInCollection;\r
104                     if (item != null && !typeInCollectionIsNullableValueType) {\r
105                         itemType = item.GetType();\r
106                     }\r
107                     ModelMetadata metadata = ModelMetadataProviders.Current.GetMetadataForType(() => item, itemType);\r
108                     string fieldName = String.Format(CultureInfo.InvariantCulture, "{0}[{1}]", fieldNameBase, index++);\r
109                     string output = templateHelper(html, metadata, fieldName, null /* templateName */, DataBoundControlMode.ReadOnly, null /* additionalViewData */);\r
110                     result.Append(output);\r
111                 }\r
112 \r
113                 return result.ToString();\r
114             }\r
115             finally {\r
116                 html.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = oldPrefix;\r
117             }\r
118         }\r
119 \r
120         internal static string DecimalTemplate(HtmlHelper html) {\r
121             if (html.ViewContext.ViewData.TemplateInfo.FormattedModelValue == html.ViewContext.ViewData.ModelMetadata.Model) {\r
122                 html.ViewContext.ViewData.TemplateInfo.FormattedModelValue = String.Format(CultureInfo.CurrentCulture, "{0:0.00}", html.ViewContext.ViewData.ModelMetadata.Model);\r
123             }\r
124 \r
125             return StringTemplate(html);\r
126         }\r
127 \r
128         internal static string EmailAddressTemplate(HtmlHelper html) {\r
129             return String.Format(CultureInfo.InvariantCulture,\r
130                                  "<a href=\"mailto:{0}\">{1}</a>",\r
131                                  html.AttributeEncode(html.ViewContext.ViewData.Model),\r
132                                  html.Encode(html.ViewContext.ViewData.TemplateInfo.FormattedModelValue));\r
133         }\r
134 \r
135         internal static string HiddenInputTemplate(HtmlHelper html) {\r
136             if (html.ViewContext.ViewData.ModelMetadata.HideSurroundingHtml) {\r
137                 return String.Empty;\r
138             }\r
139             return StringTemplate(html);\r
140         }\r
141 \r
142         internal static string HtmlTemplate(HtmlHelper html) {\r
143             return html.ViewContext.ViewData.TemplateInfo.FormattedModelValue.ToString();\r
144         }\r
145 \r
146         internal static string ObjectTemplate(HtmlHelper html) {\r
147             return ObjectTemplate(html, TemplateHelpers.TemplateHelper);\r
148         }\r
149 \r
150         internal static string ObjectTemplate(HtmlHelper html, TemplateHelpers.TemplateHelperDelegate templateHelper) {\r
151             ViewDataDictionary viewData = html.ViewContext.ViewData;\r
152             TemplateInfo templateInfo = viewData.TemplateInfo;\r
153             ModelMetadata modelMetadata = viewData.ModelMetadata;\r
154             StringBuilder builder = new StringBuilder();\r
155 \r
156             if (modelMetadata.Model == null) {    // DDB #225237\r
157                 return modelMetadata.NullDisplayText;\r
158             }\r
159 \r
160             if (templateInfo.TemplateDepth > 1) {    // DDB #224751\r
161                 return modelMetadata.SimpleDisplayText;\r
162             }\r
163 \r
164             foreach (ModelMetadata propertyMetadata in modelMetadata.Properties.Where(pm => ShouldShow(pm, templateInfo))) {\r
165                 if (!propertyMetadata.HideSurroundingHtml) {\r
166                     string label = propertyMetadata.GetDisplayName();\r
167                     if (!String.IsNullOrEmpty(label)) {\r
168                         builder.AppendFormat(CultureInfo.InvariantCulture, "<div class=\"display-label\">{0}</div>", label);\r
169                         builder.AppendLine();\r
170                     }\r
171 \r
172                     builder.Append("<div class=\"display-field\">");\r
173                 }\r
174 \r
175                 builder.Append(templateHelper(html, propertyMetadata, propertyMetadata.PropertyName, null /* templateName */, DataBoundControlMode.ReadOnly, null /* additionalViewData */));\r
176 \r
177                 if (!propertyMetadata.HideSurroundingHtml) {\r
178                     builder.AppendLine("</div>");\r
179                 }\r
180             }\r
181 \r
182             return builder.ToString();\r
183         }\r
184 \r
185         private static bool ShouldShow(ModelMetadata metadata, TemplateInfo templateInfo) {\r
186             return\r
187                 metadata.ShowForDisplay\r
188 #if false
189                 && metadata.ModelType != typeof(EntityState)\r
190 #endif
191                 && !metadata.IsComplexType\r
192                 && !templateInfo.Visited(metadata);\r
193         }\r
194 \r
195         internal static string StringTemplate(HtmlHelper html) {\r
196             return html.Encode(html.ViewContext.ViewData.TemplateInfo.FormattedModelValue);\r
197         }\r
198 \r
199         internal static string UrlTemplate(HtmlHelper html) {\r
200             return String.Format(CultureInfo.InvariantCulture,\r
201                                  "<a href=\"{0}\">{1}</a>",\r
202                                  html.AttributeEncode(html.ViewContext.ViewData.Model),\r
203                                  html.Encode(html.ViewContext.ViewData.TemplateInfo.FormattedModelValue));\r
204         }\r
205     }\r
206 }\r