MVC 3 + knockoutjs: ajouter l'attribut des données de liaison pour l'utilisation de EditorFor pour un champ booléen

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

  •  22-10-2019
  •  | 
  •  

Question

Utilisation @Html.EditorFor(model =>model.IsClient), où IsClient est un booléen, rend une liste déroulante avec Not Set, Yes and No les options.

Tout va bien.

Maintenant, je veux utiliser knockoutjs avec le dropdownlist résultant, que je l'aime, alors comment puis-je ajouter l'attribut bind-données en utilisant @ Html.EditorFor, que j'ai besoin pour knockoutjs de travailler avec cette baisse de baisse?

J'ai essayé:

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

Cependant, celui-ci utilise le paramètre objet additionalViewData, et il ne rend pas l'attribut de données BIND. Ce qui est probablement tout à fait naturel, car ce paramètre est sans doute rien à voir avec Html attributs de la balise rendu.

Cependant, ne peut trouver aucune documentation raisonnable, et aucun des autres candidats probables chercher une surcharge pour ce que je veux.

TIA suggestions.

Était-ce utile?

La solution

Brad Wilson Blogged sur les modèles d'affichage et éditeur dans ASP.NET MVC 2. vous pouvez modifier le modèle par défaut pour booléenne et ajoutez les attributs que vous avez besoin (~/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" })
}

et enfin:

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

ou décorer la propriété IsClient sur votre modèle de vue avec l'attribut UIHint:

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

et

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

va automatiquement choisir le modèle de l'éditeur personnalisé.

Autres conseils

Addendum pour les utilisateurs de knockoutjs:

La réponse de @Darin Dimitrov est grande, mais un peu trop rigide à utiliser avec knockoutjs, où les vues complexes peuvent conduire à ViewModels qui ne correspondent pas entièrement au paramètre @model.

J'ai donc fait usage du paramètre additionalViewData objet. Pour accéder au paramètre additionalViewData de votre commande EditorTemplate, consultez la question suivante de SO:

additionalViewData Accès à partir du code personnalisé EditorTemplate

Digression: Le additionalViewData est param confusion en ce qu'elle ne fait rien avec l'éditeur par défaut. Il ne vient que dans son propre modèle avec un éditeur personnalisé.

Quoi qu'il en soit, mes amendements au code de Darin sont les suivantes:

@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" })
}

Notez les lignes:

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

koObservablePrefix est là pour que je puisse ajouter un préfixe arbitraire à mon viewmodel ko.observable. Vous pouvez faire d'autres choses si vous le souhaitez.

J'utilise la variable x comme suit:

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

De cette façon, si je ne passe pas dans le additionalViewData « koObservablePrefix » tout fonctionne toujours.

Alors, maintenant je peux écrire:

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

qui rendra comme:

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

Notez "valeur: Account.IsBank". données Saucisson valeur d'attribut

Ceci est utile si, par exemple, votre point de vue modèle fortement typés est de type compte, mais dans votre accountViewModel pour votre page, vous avez une structure plus complexe, de sorte que vous devez emballer vos objets dans un observables de compte. 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
}

Si vous ne disposez pas de ce type de structure, puis, le code ramassera la structure. Il est juste une question d'adapter vos js viewmodel à cela, uhmmm, convention flexible.

Hope ce n'est pas trop confus ...

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top