|
|
1
itminus
6 年前
你就快到了。
设计
这里的困难在于我们需要为未知属性构造一个表达式。假设您想在更高级别中使用用户电话ASP for=“”/>
M0型
@ {
var m1=getm1bymagic(m0);
}
<user phones asp for=“@m1.m2….mx.user phones”>
</用户电话>
< /代码>
在标记助手中,我们可以假定每个属性的默认名称为
userphones[<index>]。<property name>
。但并非总是这样,用户可能希望将其更改为
m0.m2….mx.userphones[<index>]。<property name>
。但是,不可能知道编译时有多少个级别。
因此,我们需要一个属性
expressionfilter
来将默认表达式转换为目标表达式:
public class userPhoneStaghelper:tagHelper
{
[htmlattributename(“表达式筛选器”)]
public func<string,string>expressionfilter get;set;=e=>e;
/…
}
expressionfilterhere is a simple delegate to convert expression string.
显示代码
我只需复制您的大部分代码并做一点更改:
public class userPhoneStaghelper:tagHelper
{
专用只读IHTML发电机;
private const string forattributename=“asp for”;
公共IList<用户电话>电话获取;设置;
[视图上下文]
公共视图上下文视图上下文设置;获取;
[htmlattributename(forattributename)]
get;set;的公共模型表达式
公用用户电话Staghelper(IHTMlGenerator HTMLGenerator)
{
_ htmlgenerator=htmlgenerator;
}
[htmlattributename(“表达式筛选器”)]
public func<string,string>expressionfilter get;set;=e=>e;
//为某些属性生成标签和输入的帮助器方法
私有标记生成器GenerateSimpleInputForField(int index,propertyinfo pi)
{
var instance=phones[index];//单个用户电话的当前实例
var name=pi.name;//属性名:例如“phoneNumberID”
var v=pi.getvalue(实例);
var div=新的标记生成器(“div”);
div.addcssclass(“表单组”);
var expression=this.expressionfilter(for.name+$“[index]name”);
var explorer=for.modelexplorer.getExplorerForExpression(typeof(ilist<userphones>),o=>v);
var label=_htmlgenerator.generateLabel(viewContext、explorer、expression、name、new);
div.innerhtml.appendhtml(标签);
var input=_htmlgenerator.generateTextBox(viewContext、explorer、expression、v、null、new@class=“form control”);
div.innerhtml.appendhtml(输入);
返回div;
}
公共重写异步任务处理异步(tagHelperContext上下文,tagHelperOutput输出)
{
output.tagname=“div”;
output.tagmode=tagmode.starttagandendtag;
var type=typeof(用户电话);
propertyinfo phoneid=type.getproperty(“userphoneid”);
propertyinfo phonenumber=type.getproperty(“phonenumber”);
对于(int i=0;i<phones.count();i++){
var div1=this.generatesimpleinputforfield(i,phoneID);
var div2=this.GenerateSimpleInputForField(i,电话号码);
output.content.appendhtml(div1);
output.content.appendhtml(div2);
}
}
}
上面的processAsync()仅显示userPhoneID的标签和输入。andphoneNumberfield.如果要自动显示所有属性,只需将方法更改为:
public override async task processasync(tagHelperContext context,tagHelperOutput output)
{
output.tagname=“div”;
output.tagmode=tagmode.starttagandendtag;
对于(int i=0;i<phones.count();i++)
{
var pis=typeof(userphones.getproperties();
foreach(pis中的var pi)
{
var div=this.GenerateSimpleInputForField(i,pi);
输出.content.appendhtml(div);
}
}
}
某些字段的默认表达式字符串由以下项生成:
get_the_name_by('asp-for')+'[<index>]'+'<property name>'
< /代码>
例如:appuser.userphones[i]。<property name>
当然,它不适用于所有情况,我们可以自定义自己的expression filterto convert the expression as we like:。
在视图文件中使用用户电话:
//自定义我们自己的表达式筛选器:
@ {
var regex=new system.text.regularExpressions.regex(@“..”);
func<string,string>表达式filter=e=>。{
var m=正则匹配(e);
/…
返回m.groups[“expression”].value;
};
}
<user phones phones=“@model.appuser.user phones”
asp for=“@model.appuser.userphones”
expression filter=“expression filter”>
</用户电话>
测试用例
<div class=“row”>
@等待html.partialasync(“\u nameandid”,model.appuser)
&L/DIV & GT;
<form method=“post”>
<DIV class=“row”>
<user phones phones=“@model.appuser.user phones”asp for=“@model.appuser.user phones”expression filter=“e=>e.substring(8)”></user phones>
&L/DIV & GT;
<button type=“submit”>提交</button>
&表格/表格;
< /代码>
第一部分由局部视图生成,第二部分由用户电话生成

当你想使用<user-phones asp-for=""/> 在更高的层次上,考虑到以下代码:
@model M0
@{
var M1 = GetM1ByMagic(M0);
}
<user-phones asp-for="@M1.M2....Mx.UserPhones">
</user-phones>
在标记助手中,我们可以假定每个属性的默认名称为UserPhones[<index>].<property-name> . 但并非总是这样,用户可能希望将其更改为M0.M2....Mx.UserPhones[<index>].<property-name> . 但是,不可能知道编译时有多少个级别。
所以我们需要一个属性ExpressionFilter 要将默认表达式转换为目标表达式:
public class UserPhonesTagHelper : TagHelper
{
[HtmlAttributeName("expression-filter")]
public Func<string, string> ExpressionFilter { get; set; } = e => e;
// ...
}
这个表达式过滤器 下面是一个转换表达式字符串的简单委托。
给我看看密码
我只需复制您的大部分代码并做一点更改:
public class UserPhonesTagHelper : TagHelper
{
private readonly IHtmlGenerator _htmlGenerator;
private const string ForAttributeName = "asp-for";
public IList<UserPhones> Phones { get; set; }
[ViewContext]
public ViewContext ViewContext { set; get; }
[HtmlAttributeName(ForAttributeName)]
public ModelExpression For { get; set; }
public UserPhonesTagHelper(IHtmlGenerator htmlGenerator)
{
_htmlGenerator = htmlGenerator;
}
[HtmlAttributeName("expression-filter")]
public Func<string, string> ExpressionFilter { get; set; } = e => e;
// a helper method that generate a label and input for some property
private TagBuilder GenerateSimpleInputForField( int index ,PropertyInfo pi)
{
var instance = Phones[index];// current instance of a single UserPhone
var name = pi.Name; // property name : e.g. "PhoneNumberId"
var v = pi.GetValue(instance);
var div = new TagBuilder("div");
div.AddCssClass("form-group");
var expression = this.ExpressionFilter(For.Name + $"[{index}].{name}");
var explorer = For.ModelExplorer.GetExplorerForExpression(typeof(IList<UserPhones>), o =>v);
var label = _htmlGenerator.GenerateLabel( ViewContext, explorer, expression, name, new { } );
div.InnerHtml.AppendHtml(label);
var input = _htmlGenerator.GenerateTextBox( ViewContext, explorer, expression, v, null, new { @class = "form-control" } );
div.InnerHtml.AppendHtml(input);
return div;
}
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "div";
output.TagMode = TagMode.StartTagAndEndTag;
var type = typeof(UserPhones);
PropertyInfo phoneId= type.GetProperty("UserPhoneId");
PropertyInfo phoneNumber= type.GetProperty("PhoneNumber");
for (int i = 0; i< Phones.Count();i++) {
var div1 = this.GenerateSimpleInputForField(i,phoneId);
var div2 = this.GenerateSimpleInputForField(i,phoneNumber);
output.Content.AppendHtml(div1);
output.Content.AppendHtml(div2);
}
}
}
这个ProcessAsync() 上面只显示标签和输入UserPhoneId 和PhoneNumber 字段。如果要自动显示所有属性,只需将方法更改为:
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "div";
output.TagMode = TagMode.StartTagAndEndTag;
for (int i = 0; i < Phones.Count(); i++)
{
var pis = typeof(UserPhones).GetProperties();
foreach (var pi in pis)
{
var div = this.GenerateSimpleInputForField(i, pi);
output.Content.AppendHtml(div);
}
}
}
某些字段的默认表达式字符串由以下内容生成:
get_the_name_by('asp-for') +'[<index>]'+'<property-name>'
如:AppUser.UserPhones[i].<property-name>
当然,这不适用于所有情况,我们可以定制自己的expression-filter 如需转换表达式:
// use <user-phones> in view file :
// custom our own expression filter :
@{
var regex= new System.Text.RegularExpressions.Regex(@"...");
Func<string, string> expressionFilter = e => {
var m = regex.Match(e);
// ...
return m.Groups["expression"].Value;
};
}
<user-phones phones="@Model.AppUser.UserPhones"
asp-for="@Model.AppUser.UserPhones"
expression-filter="expressionFilter">
</user-phones>
测试用例
<div class="row">
@await Html.PartialAsync("_NameAndID", Model.AppUser)
</div>
<form method="post">
<div class="row">
<user-phones phones="@Model.AppUser.UserPhones" asp-for="@Model.AppUser.UserPhones" expression-filter="e => e.Substring(8)"></user-phones>
</div>
<button type="submit">submit</button>
</form>
第一部分由局部视图生成,第二部分由user-phones :

|