具有 data-Attribute 的 SelectListItem

在 ViewModel 上是否有一个预填充了 data 属性的 SelectList?

我想做的事

@Html.DropdownListFor(m=> m.CityId, Model.Cities);

所以它会生成如下代码:

<select id="City" class="location_city_input" name="City">
<option data-geo-lat="-32.522779" data-geo-lng="-55.765835" data-geo-zoom="6" />
<option data-geo-lat="-34.883611" data-geo-lng="-56.181944" data-geo-zoom="13" data-geo-name="Montevideo" data-child=".state1" value="1">Montevideo</option>
<option data-geo-lat="-34.816667" data-geo-lng="-55.95" data-geo-zoom="13" data-geo-name="Canelones, Ciudad de la Costa" data-child=".state41" value="41">Ciudad de la Costa</option>
</select>
65836 次浏览

您必须扩展 SelectListItem,然后扩展 DropDownListFor 以使用扩展的 SelectListItem。

看看这个解决方案:

在 Html.DropDownList 中的 < option > 下添加 Html 类标记

这是简单的解决办法。

中使用扩展方法编写并非所有内容。NET 代码。MVC 最大的好处之一就是让你可以很容易的构建你自己的 HTML。

使用 MVC4,您可以通过 helpers HTML.NameForHTML.IdFor获得表达式树上元素的 id 和名称

<select name="@Html.NameFor(Function(model) model.CityId)"
id="@Html.IdFor(Function(model) model.CityId)"
class="location_city_input">
@For Each city In Model.Cities
@<option value="@city.Value"
@(If(city.Value = Model.CityId, "selected", ""))
data-geo-lat="@city.Lat"
data-geo-lng="@city.Lng"
data-geo-zoom="@city.Zoom">
@city.Text
</option>
Next
</select>

假设 Model.Cities是公开这些属性的项的集合,那么您应该已经全部设置好了。

如果您想要可重用性,可以考虑将其作为城市枚举的任何内容的编辑器模板

我有一个类似的要求,我创建了一个扩展。希望对那些想要创建扩展的用户有所帮助。

/*cs file*/
/*This contains your information with List<vmListItem>*/
public class vmListItem
{
public int Id { get; set; }
public string Name { get; set; }
public string Tag { get; set; }
}


/*This contains the attributes in select, using List<vmAttribute>. Check cshtml */
public class vmAttribute
{
public string Key { get; set; }
public string Value { get; set; }
}


/// <summary>
/// Creates a dropdownlist using a list with data attributes included
/// </summary>
/// <param name="helper"></param>
/// <param name="id">id and name of the select</param>
/// <param name="attributes">list of attrs for select</param>
/// <param name="items"><list of options/param>
/// <param name="idSelected">id selected in option</param>
/// <param name="tagName">data-tagName you can choose the name of your tag</param>
/// <param name="textHeader">first option in select</param>
/// <returns></returns>
public static MvcHtmlString DropDownListForWithTag(this HtmlHelper helper, string id, List<vmAttribute> attributes, List<vmListItem> items, int idSelected, string tagName = "tag", string textHeader= "")
{
var select = new TagBuilder("select");
select.GenerateId(id);
select.MergeAttribute("name", id);
foreach (vmAttribute att in atributos) select.MergeAttribute(att.Key, att.Value);


TagBuilder headerOption = new TagBuilder("option");
headerOption .MergeAttribute("value", null);
headerOption .InnerHtml = textHeader;
select.InnerHtml += headerOption ;


foreach(var item in items)
{
TagBuilder option = new TagBuilder("option");
option.MergeAttribute("value", item.Id.ToString());
option.MergeAttribute("data-" + tagName, item.Tag);
if (idSelected == item.Id) option.MergeAttribute("selected", "selected");
option.InnerHtml = item.Name;


select.InnerHtml += option.ToString();
}


return new MvcHtmlString(select.ToString());
}


/*cshtml file*/
@Html.DropDownListForWithTag("MovimientoBienMotivoId", new List<vmAttribute> {
new vmAttribute("class", "form-control"),
new vmAttribute("data-val", "true"),
new vmAttribute("data-val-required", "El campo Motivo es obligatorio"),
new vmAttribute("onchange", "movValidarCambioMotivo()"),
}, (List<vmListItem>)ViewBag.MovimientoBienMotivoId, Model.MovimientoBienMotivoId, "codigo", "Seleccione")
@Html.ValidationMessageFor(model => model.ColumnId, "", new { @class = "text-danger" })




/*html results*/

enter image description here

当 MVC 将对象名称转换为属性名称时,它用“-”替换“ _”,因此它的:

@Html.DropDownList(a=>a.websiteid, Model.GetItems, new{ data_rel="selected" })

不是我的答案,答案来自 ASP > NET 论坛的布鲁斯(sqlwork.com)。

如何将 data-rel = “ select”属性添加到 htmlAttritribute 的下拉列表中?

我只是想帮忙,因为这样我就不用编程了,好好享受吧。

下面是我如何在没有扩展的情况下做到这一点,但仍然允许不引人注目的验证继续工作并被绑定到 ViewModel 属性。

创建了一个 Html Helper 以获取字符串形式的验证属性:

    public static IHtmlString GetUnobtrusiveValidationAttributesFor<TModel, TProperty>(this HtmlHelper<TModel> html, Expression<Func<TModel, TProperty>> propertySelector)
{
string propertyName = html.NameFor(propertySelector).ToString();
ModelMetadata metaData = ModelMetadata.FromLambdaExpression(propertySelector, html.ViewData);
IDictionary<string, object> attributeCollection = html.GetUnobtrusiveValidationAttributes(propertyName, metaData);


return html.Raw(String.Join(" ", attributeCollection.Select(kvp => kvp.Key + "=\"" + kvp.Value.ToString() + "\"")));
}

在视图的 select列表中使用这个助手:

<select name="@Html.NameFor(m => m.CityId)" id="@Html.IdFor(m => m.CityId)"
@Html.GetUnobtrusiveValidationAttributesFor(m => m.CityId)
class="location_city_input">
@foreach(var city in Model.Cities)
{
<option value="@city.Id.ToString()" @(city.Id == Model.CityId ? "selected" : "")
data-geo-lat="@city.Lat" data-geo-lng="@city.Lng" data-geo-zoom="@city.Zoom">
@city.Name
</option>
}
</select>

结果会是这样的:

<select id="CityId" name="CityId"
data-val-required="The SelectedTaxRateID field is required." data-val="true"
class="location_city_input">
<option value="1" selected data-geo-lat="-34.883611" data-geo-lng="-56.181944" data-geo-zoom="13">Montevideo</option>
<option value="41" data-geo-lat="-34.816667" data-geo-lng="-55.95" data-geo-zoom="13">Ciudad de la Costa</option>
</select>

我将把条件 data-属性留给您,因为这些只是形成适当的 Razor 表达式的问题。

下面是另一个添加多个属性来选择选项元素的解决方案

/// <summary>
/// itemAttributes can use to add cutom attributes for each option items
/// </summary>
public class SelectListItemWithAttributes
{
public object itemAttributes { get; set; }


public SelectListItem SelectListItem { get; set; }


}




/// <summary>
/// This can genarate a dropdown select list with multiple custom attributes for both select tag and It's option tags
/// </summary>
/// <typeparam name="TModel"></typeparam>
/// <typeparam name="TProperty"></typeparam>
/// <param name="htmlHelper"></param>
/// <param name="expression"></param>
/// <param name="list">List of SelectListItemWithAttributes items</param>
/// <param name="optionLabel">This text is show when nothing is selected (like placeholder)</param>
/// <param name="htmlAttributes">select tag element attributes</param>
/// <returns>
/// Success : html string of dropdown select list
/// expression not provides : ArgumentNullException
/// </returns>
public static MvcHtmlString DropDownListWithAttributesFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItemWithAttributes> list, string optionLabel, IDictionary<string, object> htmlAttributes = null)
{


if (expression == null)
{
throw new ArgumentNullException("expression");
}


//getting model property for binding
ModelMetadata metadata = ModelMetadata.FromLambdaExpression<TModel, TProperty>(expression, htmlHelper.ViewData);
string name = ExpressionHelper.GetExpressionText((LambdaExpression)expression);
return DropDownListWithAttributes(htmlHelper, metadata, name, list, optionLabel, htmlAttributes);




}




/// <summary>
/// genarating option items with mandotary attributes and user custom attributes, then appending to select tag
/// </summary>
/// <param name="htmlHelper"></param>
/// <param name="metadata"></param>
/// <param name="name">model property name for data binding</param>
/// <param name="list">list of SelectListItemWithAttributes</param>
/// <param name="optionLabel">This text is show when nothing is selected (like placeholder)</param>
/// <param name="htmlAttributes">select tag element attributes</param>
/// <returns>
/// Success : html string of dropdown select list
/// </returns>
private static MvcHtmlString DropDownListWithAttributes(this HtmlHelper htmlHelper, ModelMetadata metadata, string name, IEnumerable<SelectListItemWithAttributes> list, string optionLabel , IDictionary<string, object> htmlAttributes = null)
{
string fullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
if (String.IsNullOrEmpty(fullName))
{
throw new ArgumentException("name");
}


//main select tag
TagBuilder dropdown = new TagBuilder("select");
dropdown.Attributes.Add("name", fullName);


//select element must have an accessible name refer : https://dequeuniversity.com/rules/axe/4.4/select-name?application=axeAPI
dropdown.Attributes.Add("aria-label",fullName);
if(htmlAttributes != null)
{
dropdown.MergeAttributes(htmlAttributes);


}
dropdown.MergeAttributes(htmlHelper.GetUnobtrusiveValidationAttributes(name, metadata));


//initial option string with first element
var options = ("<option value='" + String.Empty + "'>" + (optionLabel == null ? "Select" : optionLabel) + "</option>");




TagBuilder option;
//Adding other option elements with all attributes
foreach (var item in list)
{
option = new TagBuilder("option");
option.MergeAttribute("value", item.SelectListItem.Value);
if(item.itemAttributes != null)
{
option.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(item.itemAttributes));


}


// including slect and disabled if provided
if (item.SelectListItem.Selected)
{
option.MergeAttribute("selected", string.Empty);


}
if (item.SelectListItem.Disabled)
{
option.MergeAttribute("disabled", string.Empty);


}




option.SetInnerText(item.SelectListItem.Text);
options += option.ToString(TagRenderMode.Normal) + "\n";
}


dropdown.InnerHtml = options;
return MvcHtmlString.Create(dropdown.ToString(TagRenderMode.Normal));
}
}