1 /* ****************************************************************************
\r
3 * Copyright (c) Microsoft Corporation. All rights reserved.
\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
9 * You must not remove this notice, or any other, from this software.
\r
11 * ***************************************************************************/
\r
13 namespace System.Web.Mvc.Html {
\r
15 using System.Collections;
\r
16 using System.Collections.Generic;
\r
18 using System.Data.Linq;
\r
19 using System.Globalization;
\r
22 using System.Web.Mvc.Resources;
\r
23 using System.Web.UI.WebControls;
\r
25 internal static class DefaultEditorTemplates {
\r
26 internal static string BooleanTemplate(HtmlHelper html) {
\r
28 if (html.ViewContext.ViewData.Model != null) {
\r
29 value = Convert.ToBoolean(html.ViewContext.ViewData.Model, CultureInfo.InvariantCulture);
\r
32 return html.ViewContext.ViewData.ModelMetadata.IsNullableValueType
\r
33 ? BooleanTemplateDropDownList(html, value)
\r
34 : BooleanTemplateCheckbox(html, value ?? false);
\r
37 private static string BooleanTemplateCheckbox(HtmlHelper html, bool value) {
\r
38 return html.CheckBox(String.Empty, value, CreateHtmlAttributes("check-box")).ToHtmlString();
\r
41 private static string BooleanTemplateDropDownList(HtmlHelper html, bool? value) {
\r
42 return html.DropDownList(String.Empty, TriStateValues(value), CreateHtmlAttributes("list-box tri-state")).ToHtmlString();
\r
46 internal static string CollectionTemplate(HtmlHelper html) {
\r
47 return CollectionTemplate(html, TemplateHelpers.TemplateHelper);
\r
50 internal static string CollectionTemplate(HtmlHelper html, TemplateHelpers.TemplateHelperDelegate templateHelper) {
\r
51 object model = html.ViewContext.ViewData.ModelMetadata.Model;
\r
52 if (model == null) {
\r
53 return String.Empty;
\r
56 IEnumerable collection = model as IEnumerable;
\r
57 if (collection == null) {
\r
58 throw new InvalidOperationException(
\r
60 CultureInfo.CurrentCulture,
\r
61 MvcResources.Templates_TypeMustImplementIEnumerable,
\r
62 model.GetType().FullName
\r
67 Type typeInCollection = typeof(string);
\r
68 Type genericEnumerableType = TypeHelpers.ExtractGenericInterface(collection.GetType(), typeof(IEnumerable<>));
\r
69 if (genericEnumerableType != null) {
\r
70 typeInCollection = genericEnumerableType.GetGenericArguments()[0];
\r
72 bool typeInCollectionIsNullableValueType = TypeHelpers.IsNullableValueType(typeInCollection);
\r
74 string oldPrefix = html.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix;
\r
77 html.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = String.Empty;
\r
79 string fieldNameBase = oldPrefix;
\r
80 StringBuilder result = new StringBuilder();
\r
83 foreach (object item in collection) {
\r
84 Type itemType = typeInCollection;
\r
85 if (item != null && !typeInCollectionIsNullableValueType) {
\r
86 itemType = item.GetType();
\r
88 ModelMetadata metadata = ModelMetadataProviders.Current.GetMetadataForType(() => item, itemType);
\r
89 string fieldName = String.Format(CultureInfo.InvariantCulture, "{0}[{1}]", fieldNameBase, index++);
\r
90 string output = templateHelper(html, metadata, fieldName, null /* templateName */, DataBoundControlMode.Edit, null /* additionalViewData */);
\r
91 result.Append(output);
\r
94 return result.ToString();
\r
97 html.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = oldPrefix;
\r
101 internal static string DecimalTemplate(HtmlHelper html) {
\r
102 if (html.ViewContext.ViewData.TemplateInfo.FormattedModelValue == html.ViewContext.ViewData.ModelMetadata.Model) {
\r
103 html.ViewContext.ViewData.TemplateInfo.FormattedModelValue = String.Format(CultureInfo.CurrentCulture, "{0:0.00}", html.ViewContext.ViewData.ModelMetadata.Model);
\r
106 return StringTemplate(html);
\r
109 internal static string HiddenInputTemplate(HtmlHelper html) {
\r
112 if (html.ViewContext.ViewData.ModelMetadata.HideSurroundingHtml) {
\r
113 result = String.Empty;
\r
116 result = DefaultDisplayTemplates.StringTemplate(html);
\r
119 object model = html.ViewContext.ViewData.Model;
\r
121 Binary modelAsBinary = model as Binary;
\r
122 if (modelAsBinary != null) {
\r
123 model = Convert.ToBase64String(modelAsBinary.ToArray());
\r
126 byte[] modelAsByteArray = model as byte[];
\r
127 if (modelAsByteArray != null) {
\r
128 model = Convert.ToBase64String(modelAsByteArray);
\r
132 result += html.Hidden(String.Empty, model).ToHtmlString();
\r
136 internal static string MultilineTextTemplate(HtmlHelper html) {
\r
137 return html.TextArea(String.Empty,
\r
138 html.ViewContext.ViewData.TemplateInfo.FormattedModelValue.ToString(),
\r
139 0 /* rows */, 0 /* columns */,
\r
140 CreateHtmlAttributes("text-box multi-line")).ToHtmlString();
\r
143 private static IDictionary<string, object> CreateHtmlAttributes(string className) {
\r
144 return new Dictionary<string, object>() {
\r
145 { "class", className }
\r
149 internal static string ObjectTemplate(HtmlHelper html) {
\r
150 return ObjectTemplate(html, TemplateHelpers.TemplateHelper);
\r
153 internal static string ObjectTemplate(HtmlHelper html, TemplateHelpers.TemplateHelperDelegate templateHelper) {
\r
154 ViewDataDictionary viewData = html.ViewContext.ViewData;
\r
155 TemplateInfo templateInfo = viewData.TemplateInfo;
\r
156 ModelMetadata modelMetadata = viewData.ModelMetadata;
\r
157 StringBuilder builder = new StringBuilder();
\r
159 if (templateInfo.TemplateDepth > 1) { // DDB #224751
\r
160 return modelMetadata.Model == null ? modelMetadata.NullDisplayText : modelMetadata.SimpleDisplayText;
\r
163 foreach (ModelMetadata propertyMetadata in modelMetadata.Properties.Where(pm => ShouldShow(pm, templateInfo))) {
\r
164 if (!propertyMetadata.HideSurroundingHtml) {
\r
165 string label = LabelExtensions.LabelHelper(html, propertyMetadata, propertyMetadata.PropertyName).ToHtmlString();
\r
166 if (!String.IsNullOrEmpty(label)) {
\r
167 builder.AppendFormat(CultureInfo.InvariantCulture, "<div class=\"editor-label\">{0}</div>\r\n", label);
\r
170 builder.Append("<div class=\"editor-field\">");
\r
173 builder.Append(templateHelper(html, propertyMetadata, propertyMetadata.PropertyName, null /* templateName */, DataBoundControlMode.Edit, null /* additionalViewData */));
\r
175 if (!propertyMetadata.HideSurroundingHtml) {
\r
176 builder.Append(" ");
\r
177 builder.Append(html.ValidationMessage(propertyMetadata.PropertyName));
\r
178 builder.Append("</div>\r\n");
\r
182 return builder.ToString();
\r
185 internal static string PasswordTemplate(HtmlHelper html) {
\r
186 return html.Password(String.Empty,
\r
187 html.ViewContext.ViewData.TemplateInfo.FormattedModelValue,
\r
188 CreateHtmlAttributes("text-box single-line password")).ToHtmlString();
\r
191 private static bool ShouldShow(ModelMetadata metadata, TemplateInfo templateInfo) {
\r
193 metadata.ShowForEdit
\r
195 && metadata.ModelType != typeof(EntityState)
\r
197 && !metadata.IsComplexType
\r
198 && !templateInfo.Visited(metadata);
\r
201 internal static string StringTemplate(HtmlHelper html) {
\r
202 return html.TextBox(String.Empty,
\r
203 html.ViewContext.ViewData.TemplateInfo.FormattedModelValue,
\r
204 CreateHtmlAttributes("text-box single-line")).ToHtmlString();
\r
207 internal static List<SelectListItem> TriStateValues(bool? value) {
\r
208 return new List<SelectListItem> {
\r
209 new SelectListItem { Text = MvcResources.Common_TriState_NotSet, Value = String.Empty, Selected = !value.HasValue },
\r
210 new SelectListItem { Text = MvcResources.Common_TriState_True, Value = "true", Selected = value.HasValue && value.Value },
\r
211 new SelectListItem { Text = MvcResources.Common_TriState_False, Value = "false", Selected = value.HasValue && !value.Value },
\r