MVC 3 + nockoutjs: добавление атрибута связывания данных при использовании Editorfor для логического поля
-
22-10-2019 - |
Вопрос
С использованием @Html.EditorFor(model =>model.IsClient)
, где isClient - логический Not Set, Yes and No
как варианты.
Все хорошо и хорошо.
Теперь я хочу использовать nockoutjs с результирующим Dropdownlist, который мне нравится, так как же добавить атрибут связывания данных с помощью @html.editorfor, который мне нужен для нокаутирования, чтобы работать с этим раскрыванием?
Я пытался:
@Html.EditorFor(model => model.IsClient, new Dictionary<string, object> { { "data-bind", "value: Account.IsClient" } })
Тем не менее, это использует параметр AceplyViewData Object, и он не производит атрибут связок данных. Что, вероятно, вполне естественно, так как этот параметр, вероятно, не имеет ничего общего с атрибутами HTML для рендерированного тега.
Тем не менее, не может найти никакой разумной документации, и ни одна из других перегрузков не выглядит, вероятно, кандидатами за то, что я хочу.
Tia любые предложения.
Решение
Брэд Уилсон В блогах о шаблонах отображения и редактора в ASP.NET MVC 2. Таким образом, вы можете изменить шаблон по умолчанию для Boolean и добавить необходимые атрибуты (~/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" })
}
и наконец:
@Html.EditorFor(model => model.IsClient, "MyTemplate")
или украсить свойство ISClient в модели вашей просмотра с помощью UIHint
атрибут:
[UIHint("MyTemplate")]
public bool? IsClient { get; set; }
а потом:
@Html.EditorFor(x => x.IsClient)
автоматически выберет пользовательский шаблон редактора.
Другие советы
Приложение для пользователей nockoutjs:
Ответ @Darin DiMitrov отличный, но немного слишком жесткий, чтобы использовать с nockoutjs, где сложные представления могут привести к просмотру, которые не совсем отображаются с параметром @Model.
Поэтому я использовал параметр opredviewData объекта. Чтобы получить доступ к параметру дополнительной проверки, из вашего пользовательского Editortemplate см. В следующем вопросе:
Доступ к дополнительным viewdata из пользовательского кода Editortemplate
Отказ: параметры дополнительного обзора сбивает с толку тем, что он ничего не делает с редактором по умолчанию. Он поступает только с помощью пользовательского шаблона редактора.
В любом случае, мои поправки к коду Дарина следующие:
@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" })
}
Обратите внимание на строки:
var x = ViewData["koObservablePrefix"];
if ((x != "") && (x != null)) { x = x + "."; }
KOOBServablePrefix есть, чтобы я мог добавить произвольный префикс в свой ViewModel KO.ObServable. Вы могли бы сделать другие вещи, если вы выберете.
Я использую переменную x следующим образом:
data_bind="value: " + x + ViewData.TemplateInfo.GetFullHtmlFieldName("")
Таким образом, если я не прохожу в дополнительной ревиз.
Итак, теперь я могу написать:
@Html.EditorFor(model => model.IsClient, "koBoolEditorFor", new { koObservablePrefix = "Account" })
это будет отображаться как:
<select class="list-box tri-state" data-bind="value: Account.IsBank" id="IsBank" name="IsBank">
Обратите внимание "Значение: account.isbank" Значение атрибута данных.
Это полезно, если, например, ваши представления сильно напечатаны модели типа, но в вашей учетной записи для вашей страницы у вас есть более сложная структура, поэтому вам необходимо упаковать свои наблюдаемые в объекте учетной записи. НАПРИМЕР:
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
}
Если у вас нет такой структуры, то код поднимет структуру. Это просто вопрос адаптации вашего ViewModel JS к этому, UHMMM, гибкому соглашению.
Надеюсь, это не слишком сбивает с толку ...