SelectListItem với dữ liệu-thuộc tính


76

Có cách nào để có Danh sách Chọn được chọn sẵn trên ViewModel với các thuộc tính dữ liệu không?

tôi muốn làm

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

vì vậy nó tạo ra mã như:

<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>

Câu trả lời:


113

Đây là giải pháp đơn giản.

Không phải mọi thứ đều phải được viết bằng phương thức mở rộng trong mã .NET. Một trong những điều tuyệt vời về MVC là nó cho phép bạn dễ dàng truy cập để xây dựng HTML của riêng mình.

Với MVC4, bạn có thể lấy id và tên của phần tử trên cây biểu thức với các trình trợ giúp HTML.NameForHTML.IdFor

<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>

Giả sử Model.Citieslà một tập hợp các mặt hàng để lộ từng thuộc tính đó. Sau đó, bạn nên tất cả các thiết lập.

Nếu bạn muốn có khả năng tái sử dụng, hãy cân nhắc đặt nó làm mẫu biên tập cho bất kỳ thứ gì là Một số thành phố


2
Thú vị ... Tôi không biết về html.namefor vv Tôi sẽ cung cấp cho nó một thử
Bart Calixto

1
Lời khuyên tuyệt vời để thêm tính linh hoạt thực sự dễ dàng cho html của bạn.
ChandlerPelhams

5
Vì razor2 bạn có thể làm đơn giản selected="@city.Value == Model.CityId"và nó sẽ tạo ra đánh dấu phù hợp (hoặc selected="selected"hoặc không có gì)
Diego

4
Làm thế nào để bạn làm cho điều này vẫn hoạt động với xác thực? Lựa chọn của tôi không tô sáng chính xác bằng màu đỏ nữa khi có lỗi xác thực.
skeletank

4
Mã đăng bởi @Diego đã không làm việc cho đến khi tôi thêm dấu ngoặc đơn:selected="@(city.Value == Model.CityId)"
Tawab Wakil

12

Bạn sẽ phải mở rộng SelectListItem, và sau đó mở rộng DropDownListFor để sử dụng SelectListItem mở rộng.

Hãy xem giải pháp này:

Thêm thẻ lớp html dưới <option> trong Html.DropDownList


1
điều này trông giống như câu trả lời chính xác nhưng có vẻ hơi xấu. Tôi thích tự mình viết lựa chọn hơn là mở rộng SelectListItem và DropDownListF Vì tôi nghĩ. Tôi không chắc.
Bart Calixto

4
Tôi không biết tại sao bạn nghĩ nó xấu xí, nhưng nó có vẻ hợp lý hơn với tôi. Mỗi SelectListItem đại diện cho một thẻ tùy chọn trong html cuối cùng và những gì bạn cần làm là thêm các thuộc tính html tùy chỉnh vào thẻ tùy chọn (SelectListItem), vì vậy việc mở rộng SelectListItem chỉ có ý nghĩa.
ataravati,

1
tôi nghĩ nó xấu từ quan điểm khuôn khổ mvc. nhưng giải pháp chính xác là làm thế nào để đối phó với.
Bart Calixto,

1
Đồng ý, khá khó chịu chỉ để thêm một số thuộc tính đơn giản :(
drogon 17/09/13

Giải pháp thực sự xấu xí. Nó đã được bao gồm trong phiên bản MVC (5.2) mới nhất hay bạn vẫn phải viết mã tùy chỉnh cho nó? Cảm ơn
Aleksander Bethke

6

Đây là cách tôi đã thực hiện điều đó mà không có tiện ích mở rộng nhưng vẫn cho phép xác thực không phô trương để tiếp tục hoạt động và bị ràng buộc với thuộc tính ViewModel.

Đã tạo Trình trợ giúp Html để nhận các thuộc tính xác thực dưới dạng chuỗi:

    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() + "\"")));
    }

Sử dụng trình trợ giúp này trong selectdanh sách ở dạng xem:

<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>

Điều này sẽ xuất ra một cái gì đó như thế này:

<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>

Tôi sẽ để lại các data-thuộc tính có điều kiện cho bạn vì đó chỉ là vấn đề hình thành các biểu thức Razor thích hợp.


3

MVC khi nó chuyển đổi tên đối tượng thành tên thuộc tính, nó liên kết "_" với "-", do đó:

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

KHÔNG PHẢI CÂU TRẢ LỜI CỦA TÔI, TRẢ LỜI TÍN DỤNG ĐẾN Giới thiệu về bruce (sqlwork.com) từ ASP> Diễn đàn NET.

Làm cách nào để thêm thuộc tính data-rel = "select" vào dropdownlist cho htmlAttributes?

CHỈ MUỐN GIÚP ĐỠ NHƯ NÀY ĐÃ GIÚP TÔI KHỎI GIẢI MÃ HACK! THƯỞNG THỨC.


6
Điều này chỉ thêm data-rel vào selectchứ không phải mỗioption
ParoX.

Thật tuyệt khi biết, mặc dù nó không thêm các thuộc tính như mong muốn (như ParoX đã đề cập).
spaark

2

Tôi đã có một yêu cầu tương tự, tôi đã tạo một tiện ích mở rộng. Hy vọng nó sẽ giúp ích cho những người muốn tạo một phần mở rộng.

/*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*/

nhập mô tả hình ảnh ở đây


Cảm ơn bạn giải pháp tốt nhất của tất cả. Tôi đã tùy chỉnh tiện ích mở rộng này để phù hợp với nhu cầu của mình.
Harry
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.