Add `DropDownList()` and `DropDownListFor()` HTML helpers
- copy over legacy MVC's `SelectExtensions`, `SelectListItem` and `SelectListGroup` - plus expected `SelectList` and `MultiSelectList` - fixup select HTML helpers to meet WebFx standards and work in new world - usual stuff: `[NotNull]`, `var`, `String` -> `string`, long lines, ... - remove `IDictionary<string, object> htmlAttributes` overloads - move longest extension method overloads into correct classes / interfaces - add `ViewDataEvaluator.Eval()` overload for an `object` container - rename lower-level helpers to make purposes more obvious - nit: move Raw() methods up from bottom of HtmlHelper.cs - use `DropDownList[For]()` in MVC sample
This commit is contained in:
parent
271c849923
commit
246bb2e3dd
|
|
@ -14,7 +14,7 @@
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<h2>Back to the main Area.</h2>
|
<h2>Back to the main Area.</h2>
|
||||||
<p>Takes you out of the area implicitly.</p>
|
<p>Takes you out of the area implicitly.</p>
|
||||||
<p><a class="btn btn-default" href="@Url.Action("Edit", "Home")">Go to Home/Edit</a></p>
|
<p><a class="btn btn-default" href="@Url.Action("Create", "Home")">Go to Home/Create</a></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<h2>Go to another action in the Area.</h2>
|
<h2>Go to another action in the Area.</h2>
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,16 @@
|
||||||
using Microsoft.AspNet.Mvc;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.AspNet.Mvc;
|
||||||
|
using Microsoft.AspNet.Mvc.Rendering;
|
||||||
using MvcSample.Web.Models;
|
using MvcSample.Web.Models;
|
||||||
|
|
||||||
namespace MvcSample.Web
|
namespace MvcSample.Web
|
||||||
{
|
{
|
||||||
public class HomeController : Controller
|
public class HomeController : Controller
|
||||||
{
|
{
|
||||||
|
private static readonly IEnumerable<SelectListItem> _addresses = CreateAddresses();
|
||||||
|
private static readonly IEnumerable<SelectListItem> _ages = CreateAges();
|
||||||
|
|
||||||
public IActionResult Index()
|
public IActionResult Index()
|
||||||
{
|
{
|
||||||
return View("MyView", User());
|
return View("MyView", User());
|
||||||
|
|
@ -22,17 +28,21 @@ namespace MvcSample.Web
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IActionResult Create()
|
public IActionResult Create()
|
||||||
{
|
{
|
||||||
|
ViewBag.Address = _addresses;
|
||||||
|
ViewBag.Ages = _ages;
|
||||||
|
|
||||||
return View();
|
return View();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Action that shows metadata when model is non-<c>null</c>.
|
/// Action that shows metadata when model is non-<c>null</c>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
public IActionResult Edit(User user)
|
||||||
public IActionResult Edit()
|
|
||||||
{
|
{
|
||||||
|
ViewBag.Address = _addresses;
|
||||||
|
ViewBag.Age = _ages;
|
||||||
ViewBag.Gift = "the banana";
|
ViewBag.Gift = "the banana";
|
||||||
ViewData.Model = new User { Name = "Name", Address = "Address in a State", Age = 37, };
|
|
||||||
return View("Create");
|
return View("Create");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -98,5 +108,27 @@ namespace MvcSample.Web
|
||||||
{
|
{
|
||||||
return View(User());
|
return View(User());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<SelectListItem> CreateAddresses()
|
||||||
|
{
|
||||||
|
var addresses = new[]
|
||||||
|
{
|
||||||
|
"121 Fake St., Redmond, WA, USA",
|
||||||
|
"123 Fake St., Redmond, WA, USA",
|
||||||
|
"125 Fake St., Redmond, WA, USA",
|
||||||
|
"127 Fake St., Redmond, WA, USA",
|
||||||
|
"129 Fake St., Redmond, WA, USA",
|
||||||
|
"131 Fake St., Redmond, WA, USA",
|
||||||
|
};
|
||||||
|
|
||||||
|
return new SelectList(addresses);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<SelectListItem> CreateAges()
|
||||||
|
{
|
||||||
|
var ages = Enumerable.Range(27, 47).Select(age => new { Age = age, Display = age.ToString("####"), });
|
||||||
|
|
||||||
|
return new SelectList(ages, dataValueField: "Age", dataTextField: "Display");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -38,6 +38,46 @@
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div style="float: left; border: thick solid limegreen; padding-right: 10px">
|
||||||
|
@using (Html.BeginForm(controllerName: "Home", actionName: "Edit", method: FormMethod.Post))
|
||||||
|
{
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label class="control-label col-md-2">Model.Name</label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@Html.TextBox("Name")
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label class="control-label col-md-2">Model.Address</label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@Html.DropDownList("Address", "Select an Address")
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label class="control-label col-md-2">Model.Age</label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@Html.DropDownListFor(model => model.Age, (IEnumerable<SelectListItem>)ViewBag.Ages, htmlAttributes: new { @class = "form-control" })
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<input type="submit" value="Save" class="btn btn-default" style="margin-left: 10px" />
|
||||||
|
</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
@helper PropertyListItem(ModelMetadata property)
|
@helper PropertyListItem(ModelMetadata property)
|
||||||
{
|
{
|
||||||
var propertyName = property.PropertyName;
|
var propertyName = property.PropertyName;
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,4 @@
|
||||||
|
|
||||||
<strong>Hello @Model.Name from Partial</strong>
|
<strong>Hello @Model.Name from Partial</strong>
|
||||||
|
|
||||||
<a href="@Url.Action("Edit", "Home")">Edit Something!</a>
|
<a href="@Url.Action("Create", "Home")">Create Something!</a>
|
||||||
|
|
@ -141,6 +141,7 @@
|
||||||
<Compile Include="Rendering\HtmlHelperLinkExtensions.cs" />
|
<Compile Include="Rendering\HtmlHelperLinkExtensions.cs" />
|
||||||
<Compile Include="Rendering\HtmlHelperNameExtensions.cs" />
|
<Compile Include="Rendering\HtmlHelperNameExtensions.cs" />
|
||||||
<Compile Include="Rendering\HtmlHelperPartialExtensions.cs" />
|
<Compile Include="Rendering\HtmlHelperPartialExtensions.cs" />
|
||||||
|
<Compile Include="Rendering\HtmlHelperSelectExtensions.cs" />
|
||||||
<Compile Include="Rendering\HtmlHelperValidationExtensions.cs" />
|
<Compile Include="Rendering\HtmlHelperValidationExtensions.cs" />
|
||||||
<Compile Include="Rendering\HtmlHelperValueExtensions.cs" />
|
<Compile Include="Rendering\HtmlHelperValueExtensions.cs" />
|
||||||
<Compile Include="Rendering\HtmlString.cs" />
|
<Compile Include="Rendering\HtmlString.cs" />
|
||||||
|
|
@ -156,7 +157,11 @@
|
||||||
<Compile Include="Rendering\IHtmlHelperOfT.cs" />
|
<Compile Include="Rendering\IHtmlHelperOfT.cs" />
|
||||||
<Compile Include="Rendering\IView.cs" />
|
<Compile Include="Rendering\IView.cs" />
|
||||||
<Compile Include="Rendering\IViewEngine.cs" />
|
<Compile Include="Rendering\IViewEngine.cs" />
|
||||||
|
<Compile Include="Rendering\MultiSelectList.cs" />
|
||||||
<Compile Include="Rendering\MvcForm.cs" />
|
<Compile Include="Rendering\MvcForm.cs" />
|
||||||
|
<Compile Include="Rendering\SelectList.cs" />
|
||||||
|
<Compile Include="Rendering\SelectListGroup.cs" />
|
||||||
|
<Compile Include="Rendering\SelectListItem.cs" />
|
||||||
<Compile Include="Rendering\ViewEngineResult.cs" />
|
<Compile Include="Rendering\ViewEngineResult.cs" />
|
||||||
<Compile Include="RouteConstraintAttribute.cs" />
|
<Compile Include="RouteConstraintAttribute.cs" />
|
||||||
<Compile Include="RouteDataActionConstraint.cs" />
|
<Compile Include="RouteDataActionConstraint.cs" />
|
||||||
|
|
|
||||||
|
|
@ -426,6 +426,54 @@ namespace Microsoft.AspNet.Mvc.Core
|
||||||
return GetString("HtmlHelper_NotContextualized");
|
return GetString("HtmlHelper_NotContextualized");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// There is no ViewData item of type '{0}' that has the key '{1}'.
|
||||||
|
/// </summary>
|
||||||
|
internal static string HtmlHelper_MissingSelectData
|
||||||
|
{
|
||||||
|
get { return GetString("HtmlHelper_MissingSelectData"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// There is no ViewData item of type '{0}' that has the key '{1}'.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatHtmlHelper_MissingSelectData(object p0, object p1)
|
||||||
|
{
|
||||||
|
return string.Format(CultureInfo.CurrentCulture, GetString("HtmlHelper_MissingSelectData"), p0, p1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The parameter '{0}' must evaluate to an IEnumerable when multiple selection is allowed.
|
||||||
|
/// </summary>
|
||||||
|
internal static string HtmlHelper_SelectExpressionNotEnumerable
|
||||||
|
{
|
||||||
|
get { return GetString("HtmlHelper_SelectExpressionNotEnumerable"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The parameter '{0}' must evaluate to an IEnumerable when multiple selection is allowed.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatHtmlHelper_SelectExpressionNotEnumerable(object p0)
|
||||||
|
{
|
||||||
|
return string.Format(CultureInfo.CurrentCulture, GetString("HtmlHelper_SelectExpressionNotEnumerable"), p0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The ViewData item that has the key '{0}' is of type '{1}' but must be of type '{2}'.
|
||||||
|
/// </summary>
|
||||||
|
internal static string HtmlHelper_WrongSelectDataType
|
||||||
|
{
|
||||||
|
get { return GetString("HtmlHelper_WrongSelectDataType"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The ViewData item that has the key '{0}' is of type '{1}' but must be of type '{2}'.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatHtmlHelper_WrongSelectDataType(object p0, object p1, object p2)
|
||||||
|
{
|
||||||
|
return string.Format(CultureInfo.CurrentCulture, GetString("HtmlHelper_WrongSelectDataType"), p0, p1, p2);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions.
|
/// Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,12 @@ namespace Microsoft.AspNet.Mvc.Rendering.Expressions
|
||||||
return EvalComplexExpression(viewData, expression);
|
return EvalComplexExpression(viewData, expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ViewDataInfo Eval(object indexableObject, [NotNull] string expression)
|
||||||
|
{
|
||||||
|
// Run through same cases as other Eval() overload but allow a null container.
|
||||||
|
return (indexableObject == null) ? null : EvalComplexExpression(indexableObject, expression);
|
||||||
|
}
|
||||||
|
|
||||||
private static ViewDataInfo EvalComplexExpression(object indexableObject, string expression)
|
private static ViewDataInfo EvalComplexExpression(object indexableObject, string expression)
|
||||||
{
|
{
|
||||||
foreach (var expressionPair in GetRightToLeftExpressions(expression))
|
foreach (var expressionPair in GetRightToLeftExpressions(expression))
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.Contracts;
|
using System.Diagnostics.Contracts;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Reflection;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Mvc.Core;
|
using Microsoft.AspNet.Mvc.Core;
|
||||||
|
|
@ -224,6 +225,17 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
additionalViewData);
|
additionalViewData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HtmlString DropDownList(string name, IEnumerable<SelectListItem> selectList, string optionLabel,
|
||||||
|
object htmlAttributes)
|
||||||
|
{
|
||||||
|
return GenerateDropDown(
|
||||||
|
metadata: null,
|
||||||
|
expression: name,
|
||||||
|
selectList: selectList,
|
||||||
|
optionLabel: optionLabel,
|
||||||
|
htmlAttributes: htmlAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
public HtmlString Hidden(string name, object value, object htmlAttributes)
|
public HtmlString Hidden(string name, object value, object htmlAttributes)
|
||||||
{
|
{
|
||||||
return GenerateHidden(metadata: null, name: name, value: value, useViewData: (value == null),
|
return GenerateHidden(metadata: null, name: name, value: value, useViewData: (value == null),
|
||||||
|
|
@ -304,6 +316,16 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
htmlAttributes: htmlAttributes);
|
htmlAttributes: htmlAttributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HtmlString Raw(string value)
|
||||||
|
{
|
||||||
|
return new HtmlString(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HtmlString Raw(object value)
|
||||||
|
{
|
||||||
|
return new HtmlString(value == null ? null : value.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
public virtual HtmlString ValidationSummary(bool excludePropertyErrors, string message, IDictionary<string, object> htmlAttributes)
|
public virtual HtmlString ValidationSummary(bool excludePropertyErrors, string message, IDictionary<string, object> htmlAttributes)
|
||||||
{
|
{
|
||||||
var formContext = ViewContext.ClientValidationEnabled ? ViewContext.FormContext : null;
|
var formContext = ViewContext.ClientValidationEnabled ? ViewContext.FormContext : null;
|
||||||
|
|
@ -522,6 +544,13 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
htmlAttributes: htmlAttributeDictionary);
|
htmlAttributes: htmlAttributeDictionary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected HtmlString GenerateDropDown(ModelMetadata metadata, string expression,
|
||||||
|
IEnumerable<SelectListItem> selectList, string optionLabel, object htmlAttributes)
|
||||||
|
{
|
||||||
|
return GenerateSelect(metadata, optionLabel, expression, selectList, allowMultiple: false,
|
||||||
|
htmlAttributes: htmlAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Writes an opening <form> tag to the response. When the user submits the form,
|
/// Writes an opening <form> tag to the response. When the user submits the form,
|
||||||
/// the request will be processed by an action method.
|
/// the request will be processed by an action method.
|
||||||
|
|
@ -713,6 +742,78 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
htmlAttributes: htmlAttributeDictionary);
|
htmlAttributes: htmlAttributeDictionary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual HtmlString GenerateSelect(ModelMetadata metadata,
|
||||||
|
string optionLabel, string name, IEnumerable<SelectListItem> selectList, bool allowMultiple,
|
||||||
|
object htmlAttributes)
|
||||||
|
{
|
||||||
|
var fullName = ViewData.TemplateInfo.GetFullHtmlFieldName(name);
|
||||||
|
if (string.IsNullOrEmpty(fullName))
|
||||||
|
{
|
||||||
|
throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, "name");
|
||||||
|
}
|
||||||
|
|
||||||
|
var usedViewData = false;
|
||||||
|
|
||||||
|
// If we got a null selectList, try to use ViewData to get the list of items.
|
||||||
|
if (selectList == null)
|
||||||
|
{
|
||||||
|
selectList = GetSelectListItems(name);
|
||||||
|
usedViewData = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var defaultValue = (allowMultiple) ?
|
||||||
|
GetModelStateValue(fullName, typeof(string[])) :
|
||||||
|
GetModelStateValue(fullName, typeof(string));
|
||||||
|
|
||||||
|
// If we haven't already used ViewData to get the entire list of items then we need to
|
||||||
|
// use the ViewData-supplied value before using the parameter-supplied value.
|
||||||
|
if (defaultValue == null && !string.IsNullOrEmpty(name))
|
||||||
|
{
|
||||||
|
if (!usedViewData)
|
||||||
|
{
|
||||||
|
defaultValue = ViewData.Eval(name);
|
||||||
|
}
|
||||||
|
else if (metadata != null)
|
||||||
|
{
|
||||||
|
defaultValue = metadata.Model;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defaultValue != null)
|
||||||
|
{
|
||||||
|
selectList = UpdateSelectListItemsWithDefaultValue(selectList, defaultValue, allowMultiple);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert each ListItem to an <option> tag and wrap them with <optgroup> if requested.
|
||||||
|
var listItemBuilder = GenerateGroupsAndOptions(optionLabel, selectList);
|
||||||
|
|
||||||
|
var tagBuilder = new TagBuilder("select")
|
||||||
|
{
|
||||||
|
InnerHtml = listItemBuilder.ToString()
|
||||||
|
};
|
||||||
|
tagBuilder.MergeAttributes(AnonymousObjectToHtmlAttributes(htmlAttributes));
|
||||||
|
tagBuilder.MergeAttribute("name", fullName, true /* replaceExisting */);
|
||||||
|
tagBuilder.GenerateId(fullName, IdAttributeDotReplacement);
|
||||||
|
if (allowMultiple)
|
||||||
|
{
|
||||||
|
tagBuilder.MergeAttribute("multiple", "multiple");
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there are any errors for a named field, we add the css attribute.
|
||||||
|
ModelState modelState;
|
||||||
|
if (ViewData.ModelState.TryGetValue(fullName, out modelState))
|
||||||
|
{
|
||||||
|
if (modelState.Errors.Count > 0)
|
||||||
|
{
|
||||||
|
tagBuilder.AddCssClass(ValidationInputCssClassName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tagBuilder.MergeAttributes(GetValidationAttributes(name, metadata));
|
||||||
|
|
||||||
|
return tagBuilder.ToHtmlString(TagRenderMode.Normal);
|
||||||
|
}
|
||||||
|
|
||||||
protected virtual HtmlString GenerateTextBox(ModelMetadata metadata, string name, object value, string format,
|
protected virtual HtmlString GenerateTextBox(ModelMetadata metadata, string name, object value, string format,
|
||||||
IDictionary<string, object> htmlAttributes)
|
IDictionary<string, object> htmlAttributes)
|
||||||
{
|
{
|
||||||
|
|
@ -838,10 +939,9 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
return tagBuilder.ToHtmlString(TagRenderMode.SelfClosing);
|
return tagBuilder.ToHtmlString(TagRenderMode.SelfClosing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected virtual HtmlString GenerateValue(string name, object value, string format, bool useViewData)
|
protected virtual HtmlString GenerateValue(string name, object value, string format, bool useViewData)
|
||||||
{
|
{
|
||||||
var fullName = ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
|
var fullName = ViewData.TemplateInfo.GetFullHtmlFieldName(name);
|
||||||
var attemptedValue = (string)GetModelStateValue(fullName, typeof(string));
|
var attemptedValue = (string)GetModelStateValue(fullName, typeof(string));
|
||||||
|
|
||||||
string resolvedValue;
|
string resolvedValue;
|
||||||
|
|
@ -892,14 +992,145 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public HtmlString Raw(string value)
|
private StringBuilder GenerateGroupsAndOptions(string optionLabel, IEnumerable<SelectListItem> selectList)
|
||||||
{
|
{
|
||||||
return new HtmlString(value);
|
var listItemBuilder = new StringBuilder();
|
||||||
|
|
||||||
|
// Make optionLabel the first item that gets rendered.
|
||||||
|
if (optionLabel != null)
|
||||||
|
{
|
||||||
|
listItemBuilder.AppendLine(GenerateOption(new SelectListItem()
|
||||||
|
{
|
||||||
|
Text = optionLabel,
|
||||||
|
Value = string.Empty,
|
||||||
|
Selected = false,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Group items in the SelectList if requested.
|
||||||
|
// Treat each item with Group == null as a member of a unique group
|
||||||
|
// so they are added according to the original order.
|
||||||
|
var groupedSelectList = selectList.GroupBy<SelectListItem, int>(
|
||||||
|
item => (item.Group == null) ? item.GetHashCode() : item.Group.GetHashCode());
|
||||||
|
foreach (var group in groupedSelectList)
|
||||||
|
{
|
||||||
|
var optGroup = group.First().Group;
|
||||||
|
|
||||||
|
// Wrap if requested.
|
||||||
|
TagBuilder groupBuilder = null;
|
||||||
|
if (optGroup != null)
|
||||||
|
{
|
||||||
|
groupBuilder = new TagBuilder("optgroup");
|
||||||
|
if (optGroup.Name != null)
|
||||||
|
{
|
||||||
|
groupBuilder.MergeAttribute("label", optGroup.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optGroup.Disabled)
|
||||||
|
{
|
||||||
|
groupBuilder.MergeAttribute("disabled", "disabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
listItemBuilder.AppendLine(groupBuilder.ToString(TagRenderMode.StartTag));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var item in group)
|
||||||
|
{
|
||||||
|
listItemBuilder.AppendLine(GenerateOption(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optGroup != null)
|
||||||
|
{
|
||||||
|
listItemBuilder.AppendLine(groupBuilder.ToString(TagRenderMode.EndTag));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return listItemBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HtmlString Raw(object value)
|
private string GenerateOption(SelectListItem item)
|
||||||
{
|
{
|
||||||
return new HtmlString(value == null ? null : value.ToString());
|
var builder = new TagBuilder("option")
|
||||||
|
{
|
||||||
|
InnerHtml = Encode(item.Text)
|
||||||
|
};
|
||||||
|
|
||||||
|
if (item.Value != null)
|
||||||
|
{
|
||||||
|
builder.Attributes["value"] = item.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.Selected)
|
||||||
|
{
|
||||||
|
builder.Attributes["selected"] = "selected";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.Disabled)
|
||||||
|
{
|
||||||
|
builder.Attributes["disabled"] = "disabled";
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.ToString(TagRenderMode.Normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<SelectListItem> GetSelectListItems(string name)
|
||||||
|
{
|
||||||
|
var value = ViewData.Eval(name);
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(Resources.FormatHtmlHelper_MissingSelectData(
|
||||||
|
"IEnumerable<SelectListItem>", name));
|
||||||
|
}
|
||||||
|
|
||||||
|
var selectList = value as IEnumerable<SelectListItem>;
|
||||||
|
if (selectList == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(Resources.FormatHtmlHelper_WrongSelectDataType(
|
||||||
|
name, value.GetType().FullName, "IEnumerable<SelectListItem>"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return selectList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<SelectListItem> UpdateSelectListItemsWithDefaultValue(
|
||||||
|
IEnumerable<SelectListItem> selectList,
|
||||||
|
object defaultValue,
|
||||||
|
bool allowMultiple)
|
||||||
|
{
|
||||||
|
IEnumerable defaultValues;
|
||||||
|
if (allowMultiple)
|
||||||
|
{
|
||||||
|
defaultValues = defaultValue as IEnumerable;
|
||||||
|
if (defaultValues == null || defaultValues is string)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
Resources.FormatHtmlHelper_SelectExpressionNotEnumerable("expression"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
defaultValues = new[] { defaultValue };
|
||||||
|
}
|
||||||
|
|
||||||
|
var values = from object value in defaultValues
|
||||||
|
select Convert.ToString(value, CultureInfo.CurrentCulture);
|
||||||
|
|
||||||
|
// ToString() by default returns an enum value's name. But selectList may use numeric values.
|
||||||
|
var enumValues = from Enum value in defaultValues.OfType<Enum>()
|
||||||
|
select value.ToString("d");
|
||||||
|
values = values.Concat(enumValues);
|
||||||
|
|
||||||
|
var selectedValues = new HashSet<string>(values, StringComparer.OrdinalIgnoreCase);
|
||||||
|
var newSelectList = new List<SelectListItem>();
|
||||||
|
foreach (SelectListItem item in selectList)
|
||||||
|
{
|
||||||
|
item.Selected = (item.Value != null) ?
|
||||||
|
selectedValues.Contains(item.Value) :
|
||||||
|
selectedValues.Contains(item.Text);
|
||||||
|
newSelectList.Add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newSelectList;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,16 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
htmlAttributes: htmlAttributes);
|
htmlAttributes: htmlAttributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public HtmlString DropDownListFor<TProperty>([NotNull] Expression<Func<TModel, TProperty>> expression,
|
||||||
|
IEnumerable<SelectListItem> selectList, string optionLabel, object htmlAttributes)
|
||||||
|
{
|
||||||
|
var metadata = ExpressionMetadataProvider.FromLambdaExpression(expression, ViewData, MetadataProvider);
|
||||||
|
|
||||||
|
return GenerateDropDown(metadata, ExpressionHelper.GetExpressionText(expression), selectList,
|
||||||
|
optionLabel, htmlAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public HtmlString DisplayFor<TValue>([NotNull] Expression<Func<TModel, TValue>> expression,
|
public HtmlString DisplayFor<TValue>([NotNull] Expression<Func<TModel, TValue>> expression,
|
||||||
string templateName,
|
string templateName,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
|
{
|
||||||
|
public static class SelectExtensions
|
||||||
|
{
|
||||||
|
public static HtmlString DropDownList<TModel>([NotNull] this IHtmlHelper<TModel> htmlHelper, string name)
|
||||||
|
{
|
||||||
|
return htmlHelper.DropDownList(name, selectList: null, optionLabel: null, htmlAttributes: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HtmlString DropDownList<TModel>([NotNull] this IHtmlHelper<TModel> htmlHelper, string name,
|
||||||
|
string optionLabel)
|
||||||
|
{
|
||||||
|
return htmlHelper.DropDownList(name, selectList: null, optionLabel: optionLabel, htmlAttributes: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HtmlString DropDownList<TModel>([NotNull] this IHtmlHelper<TModel> htmlHelper, string name,
|
||||||
|
IEnumerable<SelectListItem> selectList)
|
||||||
|
{
|
||||||
|
return htmlHelper.DropDownList(name, selectList, optionLabel: null, htmlAttributes: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HtmlString DropDownList<TModel>([NotNull] this IHtmlHelper<TModel> htmlHelper, string name,
|
||||||
|
IEnumerable<SelectListItem> selectList, object htmlAttributes)
|
||||||
|
{
|
||||||
|
return htmlHelper.DropDownList(name, selectList, optionLabel: null, htmlAttributes: htmlAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HtmlString DropDownList<TModel>([NotNull] this IHtmlHelper<TModel> htmlHelper, string name,
|
||||||
|
IEnumerable<SelectListItem> selectList, string optionLabel)
|
||||||
|
{
|
||||||
|
return htmlHelper.DropDownList(name, selectList, optionLabel, htmlAttributes: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HtmlString DropDownListFor<TModel, TProperty>([NotNull] this IHtmlHelper<TModel> htmlHelper,
|
||||||
|
[NotNull] Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> selectList)
|
||||||
|
{
|
||||||
|
return htmlHelper.DropDownListFor(expression, selectList, optionLabel: null, htmlAttributes: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HtmlString DropDownListFor<TModel, TProperty>([NotNull] this IHtmlHelper<TModel> htmlHelper,
|
||||||
|
[NotNull] Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> selectList,
|
||||||
|
object htmlAttributes)
|
||||||
|
{
|
||||||
|
return htmlHelper.DropDownListFor(expression, selectList, optionLabel: null,
|
||||||
|
htmlAttributes: htmlAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HtmlString DropDownListFor<TModel, TProperty>([NotNull] this IHtmlHelper<TModel> htmlHelper,
|
||||||
|
[NotNull] Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> selectList,
|
||||||
|
string optionLabel)
|
||||||
|
{
|
||||||
|
return htmlHelper.DropDownListFor(expression, selectList, optionLabel, htmlAttributes: null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -141,7 +141,6 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
/// Returns HTML markup for each property in the object that is represented by the specified expression, using the
|
/// Returns HTML markup for each property in the object that is represented by the specified expression, using the
|
||||||
/// template, an HTML field ID, and additional view data.
|
/// template, an HTML field ID, and additional view data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TDisplayModel">The type of the model.</typeparam>
|
|
||||||
/// <typeparam name="TValue">The type of the value.</typeparam>
|
/// <typeparam name="TValue">The type of the value.</typeparam>
|
||||||
/// <param name="expression">An expression that identifies the object that contains the properties to display.</param>
|
/// <param name="expression">An expression that identifies the object that contains the properties to display.</param>
|
||||||
/// <param name="templateName">The name of the template that is used to render the object.</param>
|
/// <param name="templateName">The name of the template that is used to render the object.</param>
|
||||||
|
|
@ -175,6 +174,43 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
/// <returns>The HTML markup for each property in the model.</returns>
|
/// <returns>The HTML markup for each property in the model.</returns>
|
||||||
HtmlString DisplayForModel(string templateName, string htmlFieldName, object additionalViewData);
|
HtmlString DisplayForModel(string templateName, string htmlFieldName, object additionalViewData);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a single-selection HTML {select} element using the specified name of the form field,
|
||||||
|
/// list items, option label, and HTML attributes.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">The name of the form field to return.</param>
|
||||||
|
/// <param name="selectList">A collection of <see href="SelectListItem"/> objects that are used to populate the
|
||||||
|
/// drop-down list.</param>
|
||||||
|
/// <param name="optionLabel">The text for a default empty item. This parameter can be null.</param>
|
||||||
|
/// <param name="htmlAttributes">An object that contains the HTML attributes to set for the {select} element.
|
||||||
|
/// Alternatively, an <see cref="IDictionary{string, object}"/> instance containing the HTML attributes.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>An HTML {select} element with an {option} subelement for each item in the list.</returns>
|
||||||
|
HtmlString DropDownList(
|
||||||
|
string name,
|
||||||
|
IEnumerable<SelectListItem> selectList,
|
||||||
|
string optionLabel,
|
||||||
|
object htmlAttributes);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a single-selection HTML {select} element for the object that is represented
|
||||||
|
/// by the specified expression using the specified list items, option label, and HTML attributes.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TProperty">The type of the value.</typeparam>
|
||||||
|
/// <param name="expression">An expression that identifies the value to display.</param>
|
||||||
|
/// <param name="selectList">A collection of <see href="SelectListItem"/> objects that are used to populate the
|
||||||
|
/// drop-down list.</param>
|
||||||
|
/// <param name="optionLabel">The text for a default empty item. This parameter can be null.</param>
|
||||||
|
/// <param name="htmlAttributes">An object that contains the HTML attributes to set for the {select} element.
|
||||||
|
/// Alternatively, an <see cref="IDictionary{string, object}"/> instance containing the HTML attributes.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>An HTML {select} element with an {option} subelement for each item in the list.</returns>
|
||||||
|
HtmlString DropDownListFor<TProperty>(
|
||||||
|
[NotNull] Expression<Func<TModel, TProperty>> expression,
|
||||||
|
IEnumerable<SelectListItem> selectList,
|
||||||
|
string optionLabel,
|
||||||
|
object htmlAttributes);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Converts the value of the specified object to an HTML-encoded string.
|
/// Converts the value of the specified object to an HTML-encoded string.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,180 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.AspNet.Mvc.Rendering.Expressions;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
|
{
|
||||||
|
public class MultiSelectList : IEnumerable<SelectListItem>
|
||||||
|
{
|
||||||
|
private IList<SelectListGroup> _groups;
|
||||||
|
|
||||||
|
public MultiSelectList([NotNull] IEnumerable items)
|
||||||
|
: this(items, selectedValues: null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public MultiSelectList([NotNull] IEnumerable items, IEnumerable selectedValues)
|
||||||
|
: this(items, dataValueField: null, dataTextField: null, selectedValues: selectedValues)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public MultiSelectList([NotNull] IEnumerable items, string dataValueField, string dataTextField)
|
||||||
|
: this(items, dataValueField, dataTextField, selectedValues: null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public MultiSelectList(
|
||||||
|
[NotNull] IEnumerable items,
|
||||||
|
string dataValueField,
|
||||||
|
string dataTextField,
|
||||||
|
IEnumerable selectedValues)
|
||||||
|
: this(items, dataValueField, dataTextField, selectedValues, dataGroupField: null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the MultiSelectList class by using the items to include in the list,
|
||||||
|
/// the data value field, the data text field, the selected values, and the data group field.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="items">The items used to build each <see cref="SelectListItem"/> of the list.</param>
|
||||||
|
/// <param name="dataValueField">The data value field. Used to match the Value property of the corresponding
|
||||||
|
/// <see cref="SelectListItem"/>.</param>
|
||||||
|
/// <param name="dataTextField">The data text field. Used to match the Text property of the corresponding
|
||||||
|
/// <see cref="SelectListItem"/>.</param>
|
||||||
|
/// <param name="selectedValues">The selected values field. Used to match the Selected property of the
|
||||||
|
/// corresponding <see cref="SelectListItem"/>.</param>
|
||||||
|
/// <param name="dataGroupField">The data group field. Used to match the Group property of the corresponding
|
||||||
|
/// <see cref="SelectListItem"/>.</param>
|
||||||
|
public MultiSelectList(
|
||||||
|
[NotNull] IEnumerable items,
|
||||||
|
string dataValueField,
|
||||||
|
string dataTextField,
|
||||||
|
IEnumerable selectedValues,
|
||||||
|
string dataGroupField)
|
||||||
|
{
|
||||||
|
Items = items;
|
||||||
|
DataValueField = dataValueField;
|
||||||
|
DataTextField = dataTextField;
|
||||||
|
SelectedValues = selectedValues;
|
||||||
|
DataGroupField = dataGroupField;
|
||||||
|
|
||||||
|
if (DataGroupField != null)
|
||||||
|
{
|
||||||
|
_groups = new List<SelectListGroup>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the data group field.
|
||||||
|
/// </summary>
|
||||||
|
public string DataGroupField { get; private set; }
|
||||||
|
|
||||||
|
public string DataTextField { get; private set; }
|
||||||
|
|
||||||
|
public string DataValueField { get; private set; }
|
||||||
|
|
||||||
|
public IEnumerable Items { get; private set; }
|
||||||
|
|
||||||
|
public IEnumerable SelectedValues { get; private set; }
|
||||||
|
|
||||||
|
public virtual IEnumerator<SelectListItem> GetEnumerator()
|
||||||
|
{
|
||||||
|
return GetListItems().GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal IList<SelectListItem> GetListItems()
|
||||||
|
{
|
||||||
|
return (!string.IsNullOrEmpty(DataValueField)) ?
|
||||||
|
GetListItemsWithValueField() :
|
||||||
|
GetListItemsWithoutValueField();
|
||||||
|
}
|
||||||
|
|
||||||
|
private IList<SelectListItem> GetListItemsWithValueField()
|
||||||
|
{
|
||||||
|
var selectedValues = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
if (SelectedValues != null)
|
||||||
|
{
|
||||||
|
selectedValues.UnionWith(from object value in SelectedValues
|
||||||
|
select Convert.ToString(value, CultureInfo.CurrentCulture));
|
||||||
|
}
|
||||||
|
|
||||||
|
var listItems = from object item in Items
|
||||||
|
let value = Eval(item, DataValueField)
|
||||||
|
select new SelectListItem
|
||||||
|
{
|
||||||
|
Group = GetGroup(item),
|
||||||
|
Value = value,
|
||||||
|
Text = Eval(item, DataTextField),
|
||||||
|
Selected = selectedValues.Contains(value)
|
||||||
|
};
|
||||||
|
return listItems.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private IList<SelectListItem> GetListItemsWithoutValueField()
|
||||||
|
{
|
||||||
|
var selectedValues = new HashSet<object>();
|
||||||
|
if (SelectedValues != null)
|
||||||
|
{
|
||||||
|
selectedValues.UnionWith(SelectedValues.Cast<object>());
|
||||||
|
}
|
||||||
|
|
||||||
|
var listItems = from object item in Items
|
||||||
|
select new SelectListItem
|
||||||
|
{
|
||||||
|
Group = GetGroup(item),
|
||||||
|
Text = Eval(item, DataTextField),
|
||||||
|
Selected = selectedValues.Contains(item)
|
||||||
|
};
|
||||||
|
return listItems.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string Eval(object container, string expression)
|
||||||
|
{
|
||||||
|
var value = container;
|
||||||
|
if (!string.IsNullOrEmpty(expression))
|
||||||
|
{
|
||||||
|
var viewDataInfo = ViewDataEvaluator.Eval(container, expression);
|
||||||
|
value = viewDataInfo.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Convert.ToString(value, CultureInfo.CurrentCulture);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SelectListGroup GetGroup(object container)
|
||||||
|
{
|
||||||
|
if (_groups == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var groupName = Eval(container, DataGroupField);
|
||||||
|
if (string.IsNullOrEmpty(groupName))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We use StringComparison.CurrentCulture because the group name is used to display as the value of
|
||||||
|
// optgroup HTML tag's label attribute.
|
||||||
|
var group = _groups.FirstOrDefault(g => string.Equals(g.Name, groupName, StringComparison.CurrentCulture));
|
||||||
|
if (group == null)
|
||||||
|
{
|
||||||
|
group = new SelectListGroup() { Name = groupName };
|
||||||
|
_groups.Add(group);
|
||||||
|
}
|
||||||
|
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IEnumerable Members
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
{
|
||||||
|
return GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
|
{
|
||||||
|
public class SelectList : MultiSelectList
|
||||||
|
{
|
||||||
|
public SelectList([NotNull] IEnumerable items)
|
||||||
|
: this(items, selectedValue: null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public SelectList([NotNull] IEnumerable items, object selectedValue)
|
||||||
|
: this(items, dataValueField: null, dataTextField: null, selectedValue: selectedValue)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public SelectList([NotNull] IEnumerable items, string dataValueField, string dataTextField)
|
||||||
|
: this(items, dataValueField, dataTextField, selectedValue: null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public SelectList(
|
||||||
|
[NotNull] IEnumerable items,
|
||||||
|
string dataValueField,
|
||||||
|
string dataTextField,
|
||||||
|
object selectedValue)
|
||||||
|
: base(items, dataValueField, dataTextField, ToEnumerable(selectedValue))
|
||||||
|
{
|
||||||
|
SelectedValue = selectedValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the SelectList class by using the specified items for the list,
|
||||||
|
/// the data value field, the data text field, a selected value, and the data group field.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="items">The items used to build each <see cref="SelectListItem"/> of the list.</param>
|
||||||
|
/// <param name="dataValueField">The data value field. Used to match the Value property of the corresponding
|
||||||
|
/// <see cref="SelectListItem"/>.</param>
|
||||||
|
/// <param name="dataTextField">The data text field. Used to match the Text property of the corresponding
|
||||||
|
/// <see cref="SelectListItem"/>.</param>
|
||||||
|
/// <param name="selectedValue">The selected values. Used to match the Selected property of the corresponding
|
||||||
|
/// <see cref="SelectListItem"/>.</param>
|
||||||
|
/// <param name="dataGroupField">The data group field. Used to match the Group property of the corresponding
|
||||||
|
/// <see cref="SelectListItem"/>.</param>
|
||||||
|
public SelectList(
|
||||||
|
[NotNull] IEnumerable items,
|
||||||
|
string dataValueField,
|
||||||
|
string dataTextField,
|
||||||
|
object selectedValue,
|
||||||
|
string dataGroupField)
|
||||||
|
: base(items, dataValueField, dataTextField, ToEnumerable(selectedValue), dataGroupField)
|
||||||
|
{
|
||||||
|
SelectedValue = selectedValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object SelectedValue { get; private set; }
|
||||||
|
|
||||||
|
private static IEnumerable ToEnumerable(object selectedValue)
|
||||||
|
{
|
||||||
|
return (selectedValue != null) ? new[] { selectedValue } : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the optgroup HTML element and its attributes.
|
||||||
|
/// In a select list, multiple groups with the same name are supported.
|
||||||
|
/// They are compared with reference equality.
|
||||||
|
/// </summary>
|
||||||
|
public class SelectListGroup
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value that indicates whether this <see cref="SelectListGroup"/> is disabled.
|
||||||
|
/// </summary>
|
||||||
|
public bool Disabled { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the value of the optgroup's label.
|
||||||
|
/// </summary>
|
||||||
|
public string Name { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
|
{
|
||||||
|
public class SelectListItem
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value that indicates whether this <see cref="SelectListItem"/> is disabled.
|
||||||
|
/// </summary>
|
||||||
|
public bool Disabled { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the optgroup HTML element this item is wrapped into.
|
||||||
|
/// In a select list, multiple groups with the same name are supported.
|
||||||
|
/// They are compared with reference equality.
|
||||||
|
/// </summary>
|
||||||
|
public SelectListGroup Group { get; set; }
|
||||||
|
|
||||||
|
public bool Selected { get; set; }
|
||||||
|
|
||||||
|
public string Text { get; set; }
|
||||||
|
|
||||||
|
public string Value { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -195,6 +195,15 @@
|
||||||
<data name="HtmlHelper_NotContextualized" xml:space="preserve">
|
<data name="HtmlHelper_NotContextualized" xml:space="preserve">
|
||||||
<value>Must call 'Contextualize' method before using this HtmlHelper instance.</value>
|
<value>Must call 'Contextualize' method before using this HtmlHelper instance.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="HtmlHelper_MissingSelectData" xml:space="preserve">
|
||||||
|
<value>There is no ViewData item of type '{0}' that has the key '{1}'.</value>
|
||||||
|
</data>
|
||||||
|
<data name="HtmlHelper_SelectExpressionNotEnumerable" xml:space="preserve">
|
||||||
|
<value>The parameter '{0}' must evaluate to an IEnumerable when multiple selection is allowed.</value>
|
||||||
|
</data>
|
||||||
|
<data name="HtmlHelper_WrongSelectDataType" xml:space="preserve">
|
||||||
|
<value>The ViewData item that has the key '{0}' is of type '{1}' but must be of type '{2}'.</value>
|
||||||
|
</data>
|
||||||
<data name="TemplateHelpers_TemplateLimitations" xml:space="preserve">
|
<data name="TemplateHelpers_TemplateLimitations" xml:space="preserve">
|
||||||
<value>Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions.</value>
|
<value>Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions.</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue