如何将对象属性作为参数传递给 Razor 组件
Posted
技术标签:
【中文标题】如何将对象属性作为参数传递给 Razor 组件【英文标题】:How Can I Pass an Object Property to a Razor Component as a Parameter 【发布时间】:2021-03-30 07:42:17 【问题描述】:我有一个剃须刀组件库,我正在其中创建自定义的、可重用的组件。我有一个“ContentItem”组件,我想简单地在组件中绑定对象的属性,然后使用反射或其他方法来发现必要的信息。举个例子:
ContentItem.razor
<div>
<div>@DisplayName</div>
<div>@PropertyValue</div>
</div>
ContentItem.razor.cs
public partial class ContentItem
#region PARAMETERS
/// <summary>
/// The property that this component will bind to
/// </summary>
[Parameter]
public **???** ObjectProperty get; set;
#endregion
#region PROTECTED
public string DisplayName;
public string PropertyValue;
#endregion
#region OVERRIDES
protected override void OnParametersSet()
try
DisplayName = //reflection or some way to get the display attribute from the Object Property
PropertyValue = //reflection or inspection of the ObjectProperty
base.OnParametersSet();
catch (Exception ex)
throw new exception("Error", ex);
#endregion
客户端应用中的页面
<div>
<ContentItem ObjectProperty="@User.FirstName" />
</div>
所以基本上你在使用“ContentItem”组件时所要做的就是传递 ObjectProperty,然后“ContentItem”组件会对该参数执行某种反射和/或检查,以根据需要呈现 html .
【问题讨论】:
【参考方案1】:您需要将类的类型、属性和值分别传递给组件。
类型将为typeof(User)
,属性名称可以从nameof(User.FirstName)
派生,并且值将是User.FirstName
值被保存为string
或其他任何值。
ContentItem
组件中的参数将如下所示:
[Parameter]
public Type ObjectType get; set;
[Parameter]
public string ObjectProperty get; set;
[Parameter]
public string ObjectValue get; set;
并且可以这样调用:
<ContentItem
ObjectType="@(typeof(User))"
ObjectProperty="@(nameof(User.FirstName))"
ObjectValue="@User.FirstName" />
所以假设你的班级是这样的:
public class User
[DisplayName("First name")]
public string FirstName get; set;
之后在组件中使用以下帮助方法获取DisplayName
:
public static string GetDisplayName(Type @type, string propertyName)
var memberInfo = @type?.GetMember(propertyName)[0];
var displayNameAttribute = memberInfo?.GetCustomAttribute<DisplayNameAttribute>();
string displayName = displayNameAttribute?.DisplayName ?? "";
return string.IsNullOrEmpty(displayName) ? propertyName : displayName;
【讨论】:
【参考方案2】:我最终用级联值/参数解决了这个问题。我有一个容器组件,它公开了一个名为“BindObject”的级联值。
<CascadingValue Name="BindObject" Value="@BindObject">
@if (BindObject != null)
@ChildContent
else
if (PlaceholderLines > 0)
<Placeholder DisplayLines="@PlaceholderLines"></Placeholder>
</CascadingValue>
然后在我的内容项组件中,我使用级联参数来获取对象。我还公开了一个“BindProperty”参数。
/// <summary>
/// When the ContentItem is placed inside of a ContentItems
/// container then the BindObject will be passed as a Cascading
/// Parameter. This ContentItem will then use reflection to
/// populate the Label and Value of this control.
/// </summary>
[CascadingParameter(Name = "BindObject")]
public object BindObject get; set;
/// <summary>
/// If a BindProperty is specified then a generic placeholder
/// will be used while the property is being loaded or evaluated.
/// The BindProperty only works when the ContentItem is placed
/// inside of a ContentItems control.
/// </summary>
[Parameter]
public string BindProperty get; set;
现在我可以在 Content Items 容器组件中指定一次绑定对象,然后将各个 Content Item 组件放入其中。我指定“BindProperty”,然后在模型上使用反射。
<ContentItems @ref="requestItems" BindObject="@jsonObject">
<ContentItem BindProperty="@nameof(jsonObject.UserId)" />
<ContentItem BindProperty="@nameof(jsonObject.FirstName)" />
<ContentItem BindProperty="@nameof(jsonObject.LastName)" />
<ContentItem BindProperty="@nameof(jsonObject.Email)" />
<ContentItem BindProperty="@nameof(jsonObject.RegionId)" />
<ContentItem BindProperty="@nameof(jsonObject.Password)" />
<ContentItem BindProperty="@nameof(jsonObject.Id)" />
</ContentItems>
我使用数据注释来指定显示名称、需求、图标等。内容项组件使用反射来消费这些信息,因此只需要在模型本身中定义它。我还编写了一些自定义验证注释来保持一切一致。
[Required]
[DisplayName("First Name:")]
[KzAlphaOnly(ErrorMessage = "Only letters are allowed here.")]
[MaxLength(16, ErrorMessage = "First name must be 16 characters or less.")]
[KzIcon(FaIcon = FaIcons.User)]
public string FirstName get; set;
[Required]
[KzAlphaOnly(ErrorMessage = "Only letters are allowed here.")]
[MaxLength(64, ErrorMessage = "Last Name name must be 64 characters or less.")]
[KzIcon(FaIcon = FaIcons.User)]
[DisplayName("Last Name:")]
public string LastName get; set;
[Required]
[StringLength(256)]
[DisplayName("Email:")]
[KzEmail]
[KzIcon(FaIcon = FaIcons.EnvelopeSquare)]
public string Email get; set;
现在我可以毫不费力地显示来自模型的信息。这对于模板、操作卡等很有用。
【讨论】:
以上是关于如何将对象属性作为参数传递给 Razor 组件的主要内容,如果未能解决你的问题,请参考以下文章
如何将具有多个对象的状态数组作为参数传递给graphql突变?