Add `ListBox()` and `ListBoxFor()` helper methods
- copy from legacy MVC - get `ListBox[For]()` methods in correct places and working - also usual stuff: `var`, `[NotNull]`, remove `IDictionary<,>` overloads - `ListBoxHelper()` -> `GenerateListBox` - already had all the bits needed in `GenerateSelect()` - special-case `null` or empty `name` in GenerateSelect() - ensure `ArgumentException` has correct parameter name - lower-level problem affected `CheckBox()` as well - use `ListBox()` and `ListBoxFor()` in MVC sample - use `ListBox()` in an editor template
This commit is contained in:
parent
7a8dc36553
commit
67b33868a3
|
|
@ -57,7 +57,7 @@ namespace MvcSample.Web
|
||||||
public ActionResult Edit(User user)
|
public ActionResult Edit(User user)
|
||||||
{
|
{
|
||||||
ViewBag.Address = _addresses;
|
ViewBag.Address = _addresses;
|
||||||
ViewBag.Age = _ages;
|
ViewBag.Ages = _ages;
|
||||||
ViewBag.Gift = "the banana";
|
ViewBag.Gift = "the banana";
|
||||||
|
|
||||||
return View("Create");
|
return View("Create");
|
||||||
|
|
|
||||||
|
|
@ -15,12 +15,19 @@
|
||||||
// See the Apache 2 License for the specific language governing
|
// See the Apache 2 License for the specific language governing
|
||||||
// permissions and limitations under the License.
|
// permissions and limitations under the License.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace MvcSample.Web.Models
|
namespace MvcSample.Web.Models
|
||||||
{
|
{
|
||||||
public class User
|
public class User
|
||||||
{
|
{
|
||||||
|
public User()
|
||||||
|
{
|
||||||
|
OwnedAddresses = new List<string>();
|
||||||
|
ParentsAges = new List<int>();
|
||||||
|
}
|
||||||
|
|
||||||
[Required]
|
[Required]
|
||||||
[MinLength(4)]
|
[MinLength(4)]
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
@ -35,5 +42,9 @@ namespace MvcSample.Web.Models
|
||||||
public string Profession { get; set; }
|
public string Profession { get; set; }
|
||||||
public string About { get; set; }
|
public string About { get; set; }
|
||||||
public string Log { get; set; }
|
public string Log { get; set; }
|
||||||
|
public IEnumerable<string> OwnedAddresses { get; private set; }
|
||||||
|
|
||||||
|
// This does not bind correctly. Only gets highest value.
|
||||||
|
public List<int> ParentsAges { get; private set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
<Content Include="Content\bootstrap.min.css" />
|
<Content Include="Content\bootstrap.min.css" />
|
||||||
<Content Include="Project.json" />
|
<Content Include="Project.json" />
|
||||||
<Content Include="Views\Home\Create.cshtml" />
|
<Content Include="Views\Home\Create.cshtml" />
|
||||||
|
<Content Include="Views\Home\EditorTemplates\IEnumerable`1.cshtml" />
|
||||||
<Content Include="Views\Home\Test.cshtml" />
|
<Content Include="Views\Home\Test.cshtml" />
|
||||||
<Content Include="Views\Home\ValidationSummary.cshtml" />
|
<Content Include="Views\Home\ValidationSummary.cshtml" />
|
||||||
<Content Include="Views\Link\Details.cshtml" />
|
<Content Include="Views\Link\Details.cshtml" />
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
@using Microsoft.AspNet.Mvc.ModelBinding
|
@using Microsoft.AspNet.Mvc.ModelBinding
|
||||||
@model User
|
@model User
|
||||||
@{
|
@{
|
||||||
ViewBag.Title = (Model == null) ? "Create Page" : "Edit Page";
|
ViewBag.Title = (Model == null && ViewData.ModelState.Count == 0) ? "Create Page" : "Edit Page";
|
||||||
if (ViewBag.Gift == null)
|
if (ViewBag.Gift == null)
|
||||||
{
|
{
|
||||||
ViewBag.Gift = "nothing";
|
ViewBag.Gift = "nothing";
|
||||||
|
|
@ -45,7 +45,7 @@
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<label class="control-label col-md-2">Model.Name</label>
|
<label class="control-label col-md-2" for="Name">Model.Name</label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@Html.TextBox("Name")
|
@Html.TextBox("Name")
|
||||||
|
|
@ -56,7 +56,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<label class="control-label col-md-2">Model.Address</label>
|
<label class="control-label col-md-2" for="Address">Model.Address</label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@Html.DropDownList("Address", "Select an Address")
|
@Html.DropDownList("Address", "Select an Address")
|
||||||
|
|
@ -64,7 +64,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<label class="control-label col-md-2">Model.Age</label>
|
<label class="control-label col-md-2" for="Age">Model.Age</label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@Html.DropDownListFor(model => model.Age, (IEnumerable<SelectListItem>)ViewBag.Ages, htmlAttributes: new { @class = "form-control" })
|
@Html.DropDownListFor(model => model.Age, (IEnumerable<SelectListItem>)ViewBag.Ages, htmlAttributes: new { @class = "form-control" })
|
||||||
|
|
@ -89,6 +89,22 @@
|
||||||
@Html.TextArea("About", "You can explain about your hobbies, work etc.", 5, 40, htmlAttributes: new { style = "font-weight:bold" })
|
@Html.TextArea("About", "You can explain about your hobbies, work etc.", 5, 40, htmlAttributes: new { style = "font-weight:bold" })
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label class="control-label col-md-2" for="OwnedAddresses">Model.OwnedAddresses</label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@Html.Editor("OwnedAddresses")
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label class="control-label col-md-2" for="ParentsAges">Model.ParentsAges</label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@Html.ListBoxFor(model => model.ParentsAges, (IEnumerable<SelectListItem>)ViewBag.Ages, htmlAttributes: new { @class = "form-control" })
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<input type="submit" value="Save" class="btn btn-default" style="margin-left: 10px" />
|
<input type="submit" value="Save" class="btn btn-default" style="margin-left: 10px" />
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
@using System.Collections.Generic
|
||||||
|
@model IEnumerable<string>
|
||||||
|
|
||||||
|
@Html.ListBox(null, (IEnumerable<SelectListItem>)ViewBag.Address)
|
||||||
|
|
@ -332,6 +332,12 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
htmlAttributes);
|
htmlAttributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public HtmlString ListBox(string name, IEnumerable<SelectListItem> selectList, object htmlAttributes)
|
||||||
|
{
|
||||||
|
return GenerateListBox(metadata: null, name: name, selectList: selectList, htmlAttributes: htmlAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual HtmlString Name(string name)
|
public virtual HtmlString Name(string name)
|
||||||
{
|
{
|
||||||
|
|
@ -866,6 +872,21 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
return tagBuilder.ToHtmlString(TagRenderMode.Normal);
|
return tagBuilder.ToHtmlString(TagRenderMode.Normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected HtmlString GenerateListBox(
|
||||||
|
ModelMetadata metadata,
|
||||||
|
string name,
|
||||||
|
IEnumerable<SelectListItem> selectList,
|
||||||
|
object htmlAttributes)
|
||||||
|
{
|
||||||
|
return GenerateSelect(
|
||||||
|
metadata,
|
||||||
|
optionLabel: null,
|
||||||
|
name: name,
|
||||||
|
selectList: selectList,
|
||||||
|
allowMultiple: true,
|
||||||
|
htmlAttributes: htmlAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
protected virtual HtmlString GeneratePassword(ModelMetadata metadata, string name, object value,
|
protected virtual HtmlString GeneratePassword(ModelMetadata metadata, string name, object value,
|
||||||
object htmlAttributes)
|
object htmlAttributes)
|
||||||
{
|
{
|
||||||
|
|
@ -974,6 +995,14 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
// If we got a null selectList, try to use ViewData to get the list of items.
|
// If we got a null selectList, try to use ViewData to get the list of items.
|
||||||
if (selectList == null)
|
if (selectList == null)
|
||||||
{
|
{
|
||||||
|
if (string.IsNullOrEmpty(name))
|
||||||
|
{
|
||||||
|
// Avoid ViewData.Eval() throwing an ArgumentException with a different parameter name. Note this
|
||||||
|
// is an extreme case since users must pass a non-null selectList to use CheckBox() or ListBox()
|
||||||
|
// in a template, where a null or empty name has meaning.
|
||||||
|
throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, "name");
|
||||||
|
}
|
||||||
|
|
||||||
selectList = GetSelectListItems(name);
|
selectList = GetSelectListItems(name);
|
||||||
usedViewData = true;
|
usedViewData = true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -170,6 +170,18 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
return GenerateLabel(metadata, ExpressionHelper.GetExpressionText(expression), labelText, htmlAttributes);
|
return GenerateLabel(metadata, ExpressionHelper.GetExpressionText(expression), labelText, htmlAttributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public HtmlString ListBoxFor<TProperty>(
|
||||||
|
[NotNull] Expression<Func<TModel, TProperty>> expression,
|
||||||
|
IEnumerable<SelectListItem> selectList,
|
||||||
|
object htmlAttributes)
|
||||||
|
{
|
||||||
|
var metadata = GetModelMetadata(expression);
|
||||||
|
var name = ExpressionHelper.GetExpressionText(expression);
|
||||||
|
|
||||||
|
return GenerateListBox(metadata, name, selectList, htmlAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public HtmlString NameFor<TProperty>([NotNull] Expression<Func<TModel, TProperty>> expression)
|
public HtmlString NameFor<TProperty>([NotNull] Expression<Func<TModel, TProperty>> expression)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -79,5 +79,26 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
{
|
{
|
||||||
return htmlHelper.DropDownListFor(expression, selectList, optionLabel, htmlAttributes: null);
|
return htmlHelper.DropDownListFor(expression, selectList, optionLabel, htmlAttributes: null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static HtmlString ListBox([NotNull] this IHtmlHelper htmlHelper, string name)
|
||||||
|
{
|
||||||
|
return htmlHelper.ListBox(name, selectList: null, htmlAttributes: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HtmlString ListBox(
|
||||||
|
[NotNull] this IHtmlHelper htmlHelper,
|
||||||
|
string name,
|
||||||
|
IEnumerable<SelectListItem> selectList)
|
||||||
|
{
|
||||||
|
return htmlHelper.ListBox(name, selectList, htmlAttributes: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HtmlString ListBoxFor<TModel, TProperty>(
|
||||||
|
[NotNull] this IHtmlHelper<TModel> htmlHelper,
|
||||||
|
[NotNull] Expression<Func<TModel, TProperty>> expression,
|
||||||
|
IEnumerable<SelectListItem> selectList)
|
||||||
|
{
|
||||||
|
return htmlHelper.ListBoxFor(expression, selectList, htmlAttributes: null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -294,6 +294,19 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
/// </returns>
|
/// </returns>
|
||||||
HtmlString Label(string expression, string labelText, object htmlAttributes);
|
HtmlString Label(string expression, string labelText, object htmlAttributes);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a multi-selection HTML {select} element using the specified name of the form field,
|
||||||
|
/// list items, 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="htmlAttributes">An object that contains the HTML attributes to set for the 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 ListBox(string name, IEnumerable<SelectListItem> selectList, object htmlAttributes);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the full HTML field name for the given expression <paramref name="name"/>.
|
/// Gets the full HTML field name for the given expression <paramref name="name"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -175,6 +175,24 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
string labelText,
|
string labelText,
|
||||||
object htmlAttributes);
|
object htmlAttributes);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a multi-selection HTML {select} element for the object that is represented by the specified
|
||||||
|
/// expression using the specified list items and HTML attributes.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TProperty">The type of the property.</typeparam>
|
||||||
|
/// <param name="expression">An expression that identifies the object that contains the properties 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="htmlAttributes">An object that contains the HTML attributes to set for the 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 ListBoxFor<TProperty>(
|
||||||
|
[NotNull] Expression<Func<TModel, TProperty>> expression,
|
||||||
|
IEnumerable<SelectListItem> selectList,
|
||||||
|
object htmlAttributes);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the full HTML field name for the given <paramref name="expression"/>.
|
/// Gets the full HTML field name for the given <paramref name="expression"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue