SelectListItem con i dati di attributi

Esiste un modo per avere un SelectList precompilato nel ViewModel con i dati di attributi ?

Voglio fare

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

così si genera il codice come :

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

 

5 Replies
  1. 97

    Ecco la soluzione più semplice.

    Non tutto deve essere scritto con metodo estensione .NET code. Una delle grandi cose su MVC si offre un facile accesso a costruire il proprio codice HTML.

    Con MVC4 è possibile ottenere l’id e il nome dell’elemento nella struttura ad albero dell’espressione con gli aiutanti HTML.NameFor e HTML.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>

    Assumendo Model.Cities è un insieme di elementi che espongono ad ogni proprietà. Quindi si dovrebbe essere tutti insieme.

    Se si desidera che la riusabilità, prendere in considerazione di fare un modello di editor per nulla di ciò che è Enumerabile di Città

    • Interessante… non sapevo che su html.namefor etc. Farò una prova
    • Ottimi consigli per l’aggiunta di facile reale flessibilità html.
    • Dal razor2 si può semplicemente fare selected="@city.Value == Model.CityId" e verrà generato il diritto di markup (sia selected="selected" o nulla)
    • Come si fa a fare questo lavoro ancora con la convalida? Il mio selezionare non correttamente evidenziato in rosso più quando c’è un errore di convalida.
    • Il codice postato da @Diego non ha funzionato fino a quando ho aggiunto le parentesi: selected="@(city.Value == Model.CityId)"
    • che suona circa la destra. Non mi funziona il codice, ho semplicemente commentato da conoscere la teoria.
    • che è il motivo per cui “Non tutto deve essere scritto con metodo estensione .NET code” non è una soluzione semplice. Per fortuna in MVC 4 e superiori, hanno fornito un modo per ottenere un discreto attributi di convalida (Html.GetUnobtrusiveValidationAttributes), ma non è abbastanza. Guardate questa risposta ad un liner, oppure si potrebbe scrivere un HTML helper per renderla più facile da leggere: stackoverflow.com/a/37748259/263832

  2. 11

    Dovrete estendere SelectListItem, e quindi estendere DropDownListFor uso esteso SelectListItem.

    Dare un’occhiata a questa soluzione:

    L’aggiunta di classe html tag <opzioni> in Html.DropDownList

    • questa sembra essere la risposta corretta, ma sembra un pò brutto. Io invece scrivo selezione di me di estendere SelectListItem e DropDownListFor penso. Non ne sono sicuro.
    • Non so perché pensi che sia brutto, ma mi sembra più logico per me. Ogni SelectListItem rappresenta un’opzione tag nel codice html finale, e che cosa dovete fare è di aggiungere attributi html il tag di opzione (SelectListItem), quindi ha senso solo per estendere la SelectListItem.
    • io penso che sia brutto dal framework mvc di prospettiva. ma la soluzione è esattamente come trattare con.
    • Concordato, abbastanza brutta, solo per aggiungere alcune semplici attributi 🙁
    • Davvero brutta soluzione. È stato coperto nella sua ultima (5.2) la versione di MVC o ancora sussulto di scrivere codice personalizzato per che? Grazie
  3. 5

    MVC quando converte i nomi degli oggetti da nomi di attributo, si relaces “_” con “-“, quindi la sua:

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

    NON la MIA risposta, la RISPOSTA di CREDITO VA A Circa bruce (sqlwork.com) da ASP>NET Forum.

    Come posso aggiungere il data- attributo in dropdownlistfor htmlAttributes?

    VOLEVO SOLO CONSIGLIARVI QUESTO MI HA SALVATO DA UNA CODIFICA DI UN HACK! GODERE di.

    • Questo solo aggiunto i dati-rel per il select non ogni option
    • Grande sapere, anche se non aggiungere gli attributi, come voluto (come ParoX citato).
  4. 2

    Ho avuto un simile requisito, ho creato una estensione. Speranza che aiuta, per chi vuole creare un’estensione.

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

    SelectListItem con i dati di attributi

    • Ringrazio soluzione migliore. Ho personalizzato questa estensione per soddisfare le mie esigenze.
  5. 2

    Ecco come ho finito di fare senza estensione, ma ancora l’attivazione di discreto convalida di continuare il lavoro, & essere associato a un ViewModel proprietà.

    Creato un Html Helper per ottenere la convalida attributi come una stringa:

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

    Utilizzare questo helper in un select lista in vista:

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

    Questo sarebbe uscita qualcosa di simile a questo:

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

    Lascio il condizionale data- attributi a voi, in quanto queste sono solo una questione di formare appropriato Rasoio espressioni.

Lascia un commento