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