我有以下模型:
class User
{
[Display(Name = "Display Name")]
public string Name { get; set; }
}
在标准Razor中,我会做类似的事情以获取“显示名称”
<label asp-for="Model.Name"></label>
但是在Blazor中似乎不起作用。有人知道如何在Blazor页面中获得显示名称而不使用反射吗?
答案 0 :(得分:5)
@ BlackFenix2我尚未发表评论(但?),但是SKPaint
应该是<Label For="@(() => Model.Name))" />
一个')'众多
为增强您的解决方案,我添加了<Label For="@(() => Model.Name)" />
,因此您可以执行此操作(例如 )@attributes="AdditionalAttributes"
<Label class="col-3 col-form-label" For="@(() => Model.Name)" />
答案 1 :(得分:4)
我的实现是替换常规Razor中的Html.DisplayNameFor()
方法;
@using System.Reflection
@using System.Linq.Expressions;
@using System.ComponentModel.DataAnnotations;
@typeparam T
@if (ChildContent == null)
{
<label>@label</label>
}
else
{
<label>
@label
@ChildContent
</label>
}
@code {
[Parameter] public Expression<Func<T>> For { get; set; }
[Parameter] public RenderFragment ChildContent { get; set; }
private string label => GetDisplayName();
private string GetDisplayName()
{
var expression = (MemberExpression)For.Body;
var value = expression.Member.GetCustomAttribute(typeof(DisplayAttribute)) as DisplayAttribute;
return value?.Name ?? expression.Member.Name ?? "";
}
}
在呼叫站点上使用以下方法之一:
<DisplayName For="@(() => object.Member)" />
或
<DisplayName For="@(() => object.Member)">
<InputText @bind-Value="object.Member" />
</DisplayName>
编辑:为澄清起见,两个版本的标记略有不同。第一个会产生:
<label>Generated DisplayName</label>
第二个会产生
<label>
Generated DisplayName
<input value="WhateverTheValueIs" />
</label>
另外,在我的实现中,我添加了一个bool
属性,仅允许以纯文本格式输出-因为事实证明,很多时候我只是想把显示名称文本输出。
答案 2 :(得分:2)
这一次(preview7),它们并不是开箱即用的功能。
创建您自己的自定义标签组件(当然需要一点点反射)并在其中封装功能非常容易:
@using System.Linq
@using System.Reflection
@using System.ComponentModel.DataAnnotations
@typeparam TItem
<label for="@fortag">@label</label>
@code {
[Parameter] public string aspfor { get; set; }
private string label => GetDisplayName(aspfor);
private string fortag => aspfor;
private string GetDisplayName(string propertyname)
{
MemberInfo myprop = typeof(TItem).GetProperty(propertyname) as MemberInfo;
var dd = myprop.GetCustomAttribute(typeof(DisplayAttribute)) as DisplayAttribute;
return dd?.Name ?? "";
}
}
并在您的.razor页面中使用它:
<CustomLabel TItem="User" aspfor="@nameof(User.Name)"></CustomLabel>
可以随意使用Expressions
或更多类型的代码(如@issac在他们的回答中解释的)来进行改进,然后请我们来解释您的经验。
在blazorfiddle尝试一下。
答案 3 :(得分:1)
@ user3224222,对不起,但是在我看来,这目前无法实现。我可能会误会,这可能很容易设置。这个问题让我很感兴趣,我将其发布在github中以了解如何实现。但是,您可以创建带有嵌入式标签元素的组件来解决您的问题。您的组件应该与内置的ValidationMessage(https://github.com/aspnet/AspNetCore/blob/4928eb3de0d80570dad93a143b52a8f5a205dac7/src/Components/Web/src/Forms/ValidationMessage.cs)相似,并具有一个名为 For 的属性,该属性可以解决问题。设置ValidationMessage的方法如下:
<ValidationMessage For="@(() => starship.MaximumAccommodation)" />
您的组件可以类似地设置:
<LabelText For="@(() => Model.Name))" />
注意:您可以按原样复制ValidationMessage类的代码并删除所有不相关的代码...您需要For属性和组件的呈现(覆盖BuildRenderTree)
祝你好运。
答案 4 :(得分:1)
我从@Kruft扩展了解决方案,使其能够使用MetadataType属性,并使用ResX Manager来维护资源文件中的显示名称。为了简短起见,我只提供了代码片段:
[MetadataType(typeof(AnforderungDtoMetadata))]
public partial class AnforderungDto : IMapBaseFrom<Anforderung>
{
public Guid Id { get; set; }
public short ReychsNr { get; set; }
public int SassenNr { get; set; }
public string AbgerufenVonName { get; set; }
}
public class AnforderungDtoMetadata
{
[Display(Name = nameof(Resources.AnforderungId), ResourceType = typeof(Resources))]
public object Id { get; set; }
[Display(Name = nameof(Resources.ReychsNr), ResourceType = typeof(Resources))]
public object ReychsNr { get; set; }
}
Blazor代码相同,我只扩展了Methode来获得显示名称:
using Microsoft.AspNetCore.Components;
using System.Linq.Expressions;
using System.ComponentModel.DataAnnotations;
using System.Reflection;
using System;
using System.Linq;
using System.Resources;
using System.Globalization;
namespace avsweb.Components
{
public partial class DisplayName<T> : ComponentBase
{
[Parameter] public Expression<Func<T>> For { get; set; }
[Parameter] public RenderFragment ChildContent { get; set; }
private string label => GetDisplayName();
private string GetDisplayName()
{
var expression = (MemberExpression)For.Body;
var value = expression.Member.GetCustomAttribute(typeof(DisplayAttribute), true) as DisplayAttribute;
if (value == null)
{
var metaData = expression.Member.DeclaringType.GetCustomAttribute(typeof(MetadataTypeAttribute), true) as MetadataTypeAttribute;
if (metaData != null)
{
var mdProp = metaData.MetadataClassType.GetProperties()
.ToList()
.Where(p => p.Name == expression.Member.Name)
.FirstOrDefault();
if (mdProp != null)
{
var mPropAttr = mdProp.GetCustomAttribute(typeof(DisplayAttribute)) as DisplayAttribute;
if (mPropAttr != null)
{
if (mPropAttr.ResourceType!=null)
{
return GetDisplayNameFromResource(mPropAttr);
}
//return mPropAttr.Name;
}
}
}
}
if (value.ResourceType!=null)
{
return GetDisplayNameFromResource(value);
}
return value?.Name ?? expression.Member.Name ?? "";
}
private static string GetDisplayNameFromResource(DisplayAttribute mPropAttr)
{
ResourceManager rm = new ResourceManager(mPropAttr.ResourceType);
var dispName = rm.GetString(mPropAttr.Name, CultureInfo.CurrentCulture);
return dispName;
}
奖金:在大型项目中,可以将资源文件放在一个普通项目中。
玩得开心!
答案 5 :(得分:0)
对此我轻描淡写,我找到了一种方法来获取传递@Issac表示的表达式的属性的显示名称。此实现将与附加到该属性的任何自定义属性一起使用。
感谢@dani herrera的初始代码
<Label For="@(() => Model.Name))" />
@using System.Linq
@using System.Reflection
@using System.ComponentModel
@using System.Linq.Expressions;
<label>@label</label>
@code {
[Parameter] public Expression<Func<string>> For { get; set; }
private string label => GetDisplayName();
private string GetDisplayName()
{
var expression = (MemberExpression)For.Body;
var value = expression.Member.GetCustomAttribute(typeof(DisplayNameAttribute)) as DisplayNameAttribute;
return value?.DisplayName ?? expression.Member.Name ?? "";
}
}