Skip to content
This repository has been archived by the owner on Dec 14, 2018. It is now read-only.

Commit

Permalink
Making the HtmlHelper.GetEnumSelectList take DisplayAttribute.GroupNa…
Browse files Browse the repository at this point in the history
…me into account to create select groups.
  • Loading branch information
stebet authored and dougbu committed Sep 29, 2015
1 parent 9243d83 commit c713aa9
Show file tree
Hide file tree
Showing 13 changed files with 191 additions and 84 deletions.
21 changes: 21 additions & 0 deletions samples/MvcSample.Web/Models/TestEnum.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;

namespace MvcSample.Web.Models
{
public enum TestEnum
{
Zero = 0,
[Display(GroupName = "Primes")]
One = 1,
[Display(GroupName = "Evens", Name = "Dos")]
Two = 2,
[Display(GroupName = "Primes")]
Three = 3,
[Display(Name = "4th")]
Four = 4
}
}
1 change: 1 addition & 0 deletions samples/MvcSample.Web/Models/User.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public User()
public string About { get; set; }
public string Log { get; set; }
public IEnumerable<string> OwnedAddresses { get; private set; }
public TestEnum EnumInformation { get; set; }

// This does not bind correctly. Only gets highest value.
public List<int> ParentsAges { get; private set; }
Expand Down
10 changes: 10 additions & 0 deletions samples/MvcSample.Web/Views/Home/Create.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,22 @@
@Html.ListBoxFor(model => model.ParentsAges, (IEnumerable<SelectListItem>)ViewBag.Ages, htmlAttributes: new { @class = "form-control" })
</td>
</tr>
<tr>
<td>
<label class="control-label col-md-2" for="Name">Model.EnumInformation</label>
</td>
<td>
@Html.DropDownList("EnumInformation", Html.GetEnumSelectList<TestEnum>())
</td>
<td></td>
</tr>
<tr>
<td>
<input type="submit" value="Save" class="btn btn-default" style="margin-left: 10px" />
</td>
<td></td>
</tr>

</table>
}
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;

namespace Microsoft.AspNet.Mvc.ModelBinding
{
/// <summary>
/// An abstraction used when grouping enum values for <see cref="ModelMetadata.EnumGroupedDisplayNamesAndValues"/>.
/// </summary>
public struct EnumGroupAndName
{
/// <summary>
/// Initializes a new instance of the EnumGroupAndName structure.
/// </summary>
/// <param name="group">The group name.</param>
/// <param name="name">The name.</param>
public EnumGroupAndName(string group, string name)
{
if (group == null)
{
throw new ArgumentNullException(nameof(group));
}

if (name == null)
{
throw new ArgumentNullException(nameof(name));
}

Group = group;
Name = name;
}

/// <summary>
/// Gets the Group name.
/// </summary>
public string Group { get; }

/// <summary>
/// Gets the name.
/// </summary>
public string Name { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,14 @@ public string PropertyName
public abstract ModelMetadata ElementMetadata { get; }

/// <summary>
/// Gets the ordered display names and values of all <see cref="Enum"/> values in
/// Gets the ordered and grouped display names and values of all <see cref="Enum"/> values in
/// <see cref="UnderlyingOrModelType"/>.
/// </summary>
/// <value>
/// An <see cref="IEnumerable{KeyValuePair{string, string}}"/> of mappings between <see cref="Enum"/> field names
/// and values. <c>null</c> if <see cref="IsEnum"/> is <c>false</c>.
/// An <see cref="IEnumerable{KeyValuePair{EnumGroupAndName, string}"/> of mappings between
/// <see cref="Enum"/> field groups, names and values. <c>null</c> if <see cref="IsEnum"/> is <c>false</c>.
/// </value>
public abstract IEnumerable<KeyValuePair<string, string>> EnumDisplayNamesAndValues { get; }
public abstract IEnumerable<KeyValuePair<EnumGroupAndName, string>> EnumGroupedDisplayNamesAndValues { get; }

/// <summary>
/// Gets the names and values of all <see cref="Enum"/> values in <see cref="UnderlyingOrModelType"/>.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,11 +272,11 @@ public override ModelMetadata ElementMetadata
}

/// <inheritdoc />
public override IEnumerable<KeyValuePair<string, string>> EnumDisplayNamesAndValues
public override IEnumerable<KeyValuePair<EnumGroupAndName, string>> EnumGroupedDisplayNamesAndValues
{
get
{
return DisplayMetadata.EnumDisplayNamesAndValues;
return DisplayMetadata.EnumGroupedDisplayNamesAndValues;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@ public class DisplayMetadata
public string EditFormatString { get; set; }

/// <summary>
/// Gets the ordered display names and values of all <see cref="System.Enum"/> values in
/// Gets the ordered and grouped display names and values of all <see cref="System.Enum"/> values in
/// <see cref="ModelMetadata.UnderlyingOrModelType"/>. See
/// <see cref="ModelMetadata.EnumDisplayNamesAndValues"/>.
/// <see cref="ModelMetadata.EnumGroupedDisplayNamesAndValues"/>.
/// </summary>
public IEnumerable<KeyValuePair<string, string>> EnumDisplayNamesAndValues { get; set; }
public IEnumerable<KeyValuePair<EnumGroupAndName, string>> EnumGroupedDisplayNamesAndValues { get; set; }

/// <summary>
/// Gets the names and values of all <see cref="System.Enum"/> values in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,19 +120,20 @@ public void GetDisplayMetadata(DisplayMetadataProviderContext context)
// Order EnumDisplayNamesAndValues to match Enum.GetNames(). That method orders by absolute value,
// then its behavior is undefined (but hopefully stable). Add to EnumNamesAndValues in same order but
// Dictionary does not guarantee order will be preserved.
var displayNamesAndValues = new List<KeyValuePair<string, string>>();
var groupedDisplayNamesAndValues = new List<KeyValuePair<EnumGroupAndName, string>>();
var namesAndValues = new Dictionary<string, string>();
foreach (var name in Enum.GetNames(underlyingType))
{
var field = underlyingType.GetField(name);
var displayName = GetDisplayName(field);
var groupName = GetDisplayGroup(field);
var value = ((Enum)field.GetValue(obj: null)).ToString("d");

displayNamesAndValues.Add(new KeyValuePair<string, string>(displayName, value));
groupedDisplayNamesAndValues.Add(new KeyValuePair<EnumGroupAndName, string>(new EnumGroupAndName(groupName, displayName), value));
namesAndValues.Add(name, value);
}

displayMetadata.EnumDisplayNamesAndValues = displayNamesAndValues;
displayMetadata.EnumGroupedDisplayNamesAndValues = groupedDisplayNamesAndValues;
displayMetadata.EnumNamesAndValues = namesAndValues;
}

Expand Down Expand Up @@ -258,5 +259,22 @@ private static string GetDisplayName(FieldInfo field)

return field.Name;
}

// Return non-empty group specified in a [Display] attribute for a field, if any; string.Empty otherwise.
private static string GetDisplayGroup(FieldInfo field)
{
var display = field.GetCustomAttribute<DisplayAttribute>(inherit: false);
if (display != null)
{
// Note [Display(Group = "")] is allowed.
var group = display.GetGroupName();
if (group != null)
{
return group;
}
}

return string.Empty;
}
}
}
15 changes: 13 additions & 2 deletions src/Microsoft.AspNet.Mvc.ViewFeatures/ViewFeatures/HtmlHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1168,14 +1168,25 @@ protected virtual IEnumerable<SelectListItem> GetEnumSelectList(ModelMetadata me
}

var selectList = new List<SelectListItem>();
foreach (var keyValuePair in metadata.EnumDisplayNamesAndValues)
var groupList = new Dictionary<string, SelectListGroup>();
foreach (var keyValuePair in metadata.EnumGroupedDisplayNamesAndValues)
{
var selectListItem = new SelectListItem
{
Text = keyValuePair.Key,
Text = keyValuePair.Key.Name,
Value = keyValuePair.Value,
};

if (!string.IsNullOrEmpty(keyValuePair.Key.Group))
{
if (!groupList.ContainsKey(keyValuePair.Key.Group))
{
groupList[keyValuePair.Key.Group] = new SelectListGroup() { Name = keyValuePair.Key.Group };
}

selectListItem.Group = groupList[keyValuePair.Key.Group];
}

selectList.Add(selectListItem);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ public override ModelMetadata ElementMetadata
}
}

public override IEnumerable<KeyValuePair<string, string>> EnumDisplayNamesAndValues
public override IEnumerable<KeyValuePair<EnumGroupAndName, string>> EnumGroupedDisplayNamesAndValues
{
get
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public void DefaultValues()
Assert.Null(metadata.DisplayName);
Assert.Null(metadata.EditFormatString);
Assert.Null(metadata.ElementMetadata);
Assert.Null(metadata.EnumDisplayNamesAndValues);
Assert.Null(metadata.EnumGroupedDisplayNamesAndValues);
Assert.Null(metadata.EnumNamesAndValues);
Assert.Null(metadata.NullDisplayText);
Assert.Null(metadata.TemplateHint);
Expand Down
Loading

0 comments on commit c713aa9

Please sign in to comment.