MVC 3 + knockoutjs: aggiungere l'attributo data-bind quando si utilizza EditorFor per un campo booleano

StackOverflow https://stackoverflow.com/questions/7302434

  •  22-10-2019
  •  | 
  •  

Domanda

Utilizzando @Html.EditorFor(model =>model.IsClient), dove IsClient è un valore booleano, rende un elenco a discesa con Not Set, Yes and No come le opzioni in basso.

Tutto bene.

Ora voglio usare knockoutjs con la DropDownList risultante, che mi piace, quindi come faccio ad aggiungere l'attributo data-bind utilizzando @ Html.EditorFor, che ho bisogno per knockoutjs per lavorare con questa discesa?

ho provato:

@Html.EditorFor(model => model.IsClient, new Dictionary<string, object> { { "data-bind", "value: Account.IsClient" } })

Tuttavia, questo utilizza il parametro oggetto additionalViewData, e non rende l'attributo data-bind. Quale è probabilmente del tutto naturale, in quanto questo parametro è probabilmente nulla a che fare con attributi HTML per il tag reso.

Tuttavia, non può trovare alcuna documentazione ragionevole, e nessuno degli altri sovraccarichi cercare probabili candidati per quello che voglio.

TIA eventuali suggerimenti.

È stato utile?

Soluzione

bloggato su modelli di visualizzazione ed editor in ASP.NET MVC 2. Così si potrebbe modificare il modello predefinito per booleano e aggiungere gli attributi è necessario (~/Views/Shared/EditorTemplates/MyTemplate.cshtml):

@{
    bool? value = null;
    if (ViewData.Model != null) 
    {
        value = Convert.ToBoolean(ViewData.Model, System.Globalization.CultureInfo.InvariantCulture);
    }

    var triStateValues = new List<SelectListItem> 
    {
        new SelectListItem 
        { 
            Text = "Not Set",
            Value = String.Empty,
            Selected = !value.HasValue 
        },
        new SelectListItem 
        { 
            Text = "True",
            Value = "true",
            Selected = value.HasValue && value.Value 
        },
        new SelectListItem 
        { 
            Text = "False",
            Value = "false",
            Selected = value.HasValue && !value.Value 
        },
    };
}

@if (ViewData.ModelMetadata.IsNullableValueType) 
{
    <!-- TODO: here you can use any attributes you like -->
    @Html.DropDownList(
        "", 
        triStateValues, 
        new { 
            @class = "list-box tri-state", 
            data_bind="value: " + ViewData.TemplateInfo.GetFullHtmlFieldName("") // you could also use ViewData.ModelMetadata.PropertyName if you want to get only the property name and not the entire navigation hierarchy name
        }
    )
} 
else 
{
    @Html.CheckBox("", value ?? false, new { @class = "check-box" })
}

e infine

@Html.EditorFor(model => model.IsClient, "MyTemplate")

o decorare la proprietà IsClient del modello di visualizzazione con l'attributo UIHint:

[UIHint("MyTemplate")]
public bool? IsClient { get; set; }

e poi:

 @Html.EditorFor(x => x.IsClient)

sceglierà automaticamente il modello editor personalizzato.

Altri suggerimenti

Addendum per gli utenti knockoutjs:

La risposta di @Darin Dimitrov è grande, ma un po 'troppo rigido per l'uso con knockoutjs, dove panorami complessi possono portare a ViewModels che non del tutto mappano al parametro @Model.

Così ho fatto uso del parametro dell'oggetto additionalViewData. Per accedere al parametro additionalViewData dal EditorTemplate personalizzato, consultare la seguente questione SO:

Accesso additionalViewData dal codice personalizzato EditorTemplate

Digressione: Il param additionalViewData è fonte di confusione in quanto non fa nulla con l'editor di default. Viene fornito solo il meglio di sé con un editor di modelli personalizzati.

In ogni caso, i miei emendamenti al codice di Darin sono i seguenti:

@if (ViewData.ModelMetadata.IsNullableValueType) 
{
    var x = ViewData["koObservablePrefix"];
    if ((x != "") && (x != null)) { x = x + "."; }
    @Html.DropDownList(
        "", 
        triStateValues, 
        new { 
            @class = "list-box tri-state", 
            data_bind="value: " + x + ViewData.TemplateInfo.GetFullHtmlFieldName("") // or you could also use ViewData.ModelMetadata.PropertyName if you want to get only the property name and not the entire navigation hierarchy name
        }
    )
} 
else 
{
    @Html.CheckBox("", value ?? false, new { @class = "check-box" })
}

Si notino le linee:

var x = ViewData["koObservablePrefix"];
if ((x != "") && (x != null)) { x = x + "."; }

koObservablePrefix è là in modo che posso aggiungere un prefisso arbitrario al mio ViewModel ko.observable. Si potrebbe fare altre cose, se lo desiderano.

I Utilizzare la variabile x come segue:

data_bind="value: " + x + ViewData.TemplateInfo.GetFullHtmlFieldName("")

In questo modo, se non passano nella additionalViewData "koObservablePrefix" funziona ancora tutti.

Quindi, ora posso scrivere:

@Html.EditorFor(model => model.IsClient, "koBoolEditorFor", new { koObservablePrefix = "Account" })

che renderà come:

<select class="list-box tri-state" data-bind="value: Account.IsBank" id="IsBank" name="IsBank">

Si noti la "Valore: Account.IsBank". valore di attributo data-bind

Questo è utile se, ad esempio, le vostre opinioni digitati con forza il modello è di tipo di account, ma nel tuo accountViewModel per la tua pagina, è avere una struttura più complessa, quindi è necessario per confezionare i vostri osservabili in un oggetto account. EG:

function account(accountId, personId, accountName, isClient, isProvider, isBank) {

    this.AccountId   = ko.observable(accountId);
    this.PersonId    = ko.observable(personId);
    this.AccountName = ko.observable(accountName);
    this.IsClient    = ko.observable(isClient);
    this.IsProvider  = ko.observable(isProvider);
    this.IsBank      = ko.observable(isBank);
}

function accountViewModel() { 

    var self = this;

    this.selectedCostCentre = ko.observable('');            
    this.Account = new account(@Model.AccountId, @Model.PersonId, '@Model.AccountName', '@Model.IsClient','@Model.IsProvider', '@Model.IsBank');
              // etc. etc
}

Se non si dispone di questo tipo di struttura, quindi, il codice prenderà la struttura. E 'solo una questione di sartoria tuoi js ViewModel a questo, uhmmm, convention flessibile.

Non

Spero che questo è troppo confusa ...

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top