Невозможно сделать это с InputTagHelper
напрямую. Для получения дополнительной информации см. Бритва / проблемы # 926 , а также аналогичный вопрос по SO .
A Walkaournd
Но, как обходной путь, вы могли бы использовать пользовательский HtmlHelper<TModel>
(как и @Html
) для достижения той же цели . Ваш частичный вид может выглядеть так:
@model App.TagHelpers.PartialVM
@{
var PartialHtml = Model.HtmlHelper;
}
@PartialHtml.Label(Model.NewFor.Name,Model.NewFor.Name)
@PartialHtml.TextBox(Model.NewFor.Name, Model.NewModel)
А именно, используйте @Html.Label()
& @Html.TextBot
вместо <label>
& <input>
.
Здесь PartialVM
- это простой класс, который содержит метаинформацию о модели:
public class PartialVM
{
public PartialVM(ModelExpression originalFor, IHtmlHelper htmlHelper)
{
var originalExplorer = originalFor.ModelExplorer;
OriginalFor = originalFor;
OriginalExplorer = originalExplorer;
NewModel = originalExplorer.Model;
NewModelExplorer = originalExplorer.GetExplorerForModel(NewModel);
NewFor = new ModelExpression(OriginalFor.Name, NewModelExplorer);
this.HtmlHelper = htmlHelper;
}
public IHtmlHelper HtmlHelper { get; set; }
public ModelExpression OriginalFor { get; set; }
public ModelExplorer OriginalExplorer { get; set; }
public ModelExpression NewFor { get; set; }
public ModelExplorer NewModelExplorer { get; set; }
public Object NewModel { get; set; }
}
Обратите внимание, что IHtmlHelper
на самом деле IHtmlHelper<TSomeDynamicModel>
вместо простого IHtmlHelper
.
Наконец, измените TagHelper
, как показано ниже:
[HtmlTargetElement("my-custom-input")]
public class MyCustomInputTagHelper : TagHelper
{
private readonly IServiceProvider _sp;
[ViewContext]
public ViewContext ViewContext { set; get; }
public ModelExpression For { get; set; }
public MyCustomInputTagHelper(IServiceProvider sp)
{
this._sp = sp;
}
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
base.Process(context, output);
var originExplorer = For.ModelExplorer;
var newModel = originExplorer.Model;
var newExplorer = originExplorer.GetExplorerForModel(newModel);
var newFor = new ModelExpression(For.Name, newExplorer);
var ModelType = originExplorer.Container.Model.GetType();
var htmlHelperType = typeof(IHtmlHelper<>).MakeGenericType(ModelType);
var htmlHelper = this._sp.GetService(htmlHelperType) as IHtmlHelper; // get the actual IHtmlHelper<TModel>
(htmlHelper as IViewContextAware).Contextualize(ViewContext);
var vm = new PartialVM(For, htmlHelper);
var writer = new StringWriter();
var content = await htmlHelper.PartialAsync("~/Views/Partials/TagHelpers/MyDateInput.cshtml", vm);
output.TagName = "div";
output.TagMode = TagMode.StartTagAndEndTag;
output.Content.SetHtmlContent(content);
}
}
Теперь вы можете передать любую asp-for
строку выражения для свойства For
вашего TagHelper
, и оно должно работать как положено.
Контрольный пример:
Предположим, у нас есть модель Dto:
public class XModel {
public int Id { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public string ActiveStatus{ get; set; }
}
Вы можете сделать это следующим образом:
/// the action method looks like:
/// var model = new XModel {
/// StartDate = DateTime.Now,
/// EndDate = DateTime.Now.AddYears(1),
/// ActiveStatus = "Active",
/// };
/// return View(model);
@model XModel
<my-custom-input For="StartDate" />
<my-custom-input For="EndDate" />
<my-custom-input For="ActiveStatus" />
Вот скриншот, когда он рендерит: