gpt4 book ai didi

c# - Html.Label 用于使用对象的 DisplayName 而不是属性

转载 作者:太空狗 更新时间:2023-10-29 23:39:46 25 4
gpt4 key购买 nike

给定一个像这样的 View 模型:

public class ParentViewModel
{
public object ChildViewModel { get; set; }
}

如果我使用 Html.LabelFor像这样:

@Html.LabelFor(model => model.ChildViewModel)

我会得到这样的输出:

<label for="Model_ChildViewModel">ChildViewModel</label>

不过,我真正想要的是让生成的标签使用 DisplayName应用于对象的属性 E.G.

[DisplayName("My Custom Label")]
public class ChildViewModel
{
}

输出为:

<label for="Model_ChildViewModel">My Custom Label</label>

据我所知,Html.LabelFor方法接受一个需要属性的表达式,它将查找 DisplayName该属性而不是对象本身的属性。

我创建了一个 Html 辅助方法来实现我想要的,如下所示:

public static IHtmlString CreateLabel<TModel>(this HtmlHelper html, Func<TModel, object> func) 
where TModel : class
{
TagBuilder tb = new TagBuilder("label");

var model = html.ViewData.Model as TModel;
if (model != null)
{
object obj = func(model);
if (obj != null)
{
var attribute = obj.GetType().GetCustomAttributes(
typeof(DisplayNameAttribute), true)
.FirstOrDefault() as DisplayNameAttribute;

if (attribute != null)
{
tb.InnerHtml = attribute.DisplayName;
return MvcHtmlString.Create(tb.ToString());
}
else
{
tb.InnerHtml = obj.ToString();
return MvcHtmlString.Create(tb.ToString());
}
}
}

tb.InnerHtml = html.ViewData.Model.ToString();
return MvcHtmlString.Create(tb.ToString());
}

我的助手没有采用表达式,而是采用了 Func<TModel, object>它返回我要检查 DisplayName 的对象属性。

我遇到的第一个问题是当我试图像这样在 razor 中调用这个方法时:

@Html.CreateLabel(model => model.ChildObject)

我收到以下错误:

The type arguments for method 'CreateLabel<TModel>(this HtmlHelper,
Func<TModel, object>) cannot be inferred from usage. Try specifying
the arguments explicitly.'

所以我改为这样调用方法:

 @{ Html.CreateLabel<ChildViewModel>(model => model.ChildObject); }

但没有渲染。如果我使用调试器逐步执行我的帮助程序方法,则会生成 label 标记,但在呈现我的页面时不会显示任何内容。

所以我的问题是:

  • 如何解决此问题以便为我的 View 生成标签?
  • 我必须做什么才能推断出通用参数?
  • 有没有什么方法可以编写 Html 帮助程序来做同样的事情,但使用表达式?我没有使用表达式的经验,所以不知道从哪里开始。

更新

我想我应该发布最终代码,因为我做了一些小改动。首先,我查看了 MVC 源代码中的帮助程序,并决定根据提供的示例将方法拆分为三个独立的方法。我还删除了所有 TagBuilder我真正需要的是生成要在 <legend></legend> 之间注入(inject)的文本标签。最终代码如下。再次感谢 Sylon 帮助我解决这个问题。

public static IHtmlString LegendTextFor<TModel, TObject>(this HtmlHelper<TModel> html, Expression<Func<TModel, TObject>> expression)
{
return LegendTextHelper(html,
ModelMetadata.FromLambdaExpression(expression, html.ViewData),
ExpressionHelper.GetExpressionText(expression),
expression.Compile().Invoke(html.ViewData.Model));
}

private static IHtmlString LegendTextHelper<TModel, TObject>(this HtmlHelper<TModel> html, ModelMetadata metadata, string htmlFieldName, TObject value)
{
string resolvedLabelText = metadata.DisplayName ?? value.GetDisplayName() ?? metadata.PropertyName ?? htmlFieldName.Split('.').Last();

if (String.IsNullOrEmpty(resolvedLabelText))
return MvcHtmlString.Empty;

return MvcHtmlString.Create(resolvedLabelText);
}

private static string GetDisplayName<T>(this T obj)
{
if (obj != null)
{
var attribute = obj.GetType()
.GetCustomAttributes(typeof(DisplayNameAttribute), false)
.Cast<DisplayNameAttribute>()
.FirstOrDefault();

return attribute != null ? attribute.DisplayName : null;
}
else
{
return null;
}
}

最佳答案

我刚刚为标签创建了一个自定义的 Html 帮助程序,它可以执行您想要的操作:

HTML 助手:

public static class HtmlHelperExtensions
{

public static MvcHtmlString LabelForCustom<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
{
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);

string customDisplayName = null;

var value = expression.Compile().Invoke(html.ViewData.Model);

if (value != null)
{
var attribute = value.GetType().GetCustomAttributes(typeof(DisplayNameAttribute), false)
.Cast<DisplayNameAttribute>()
.FirstOrDefault();

customDisplayName = attribute != null ? attribute.DisplayName : null;
}

string htmlFieldName = ExpressionHelper.GetExpressionText(expression);
string labelText = metadata.DisplayName ?? customDisplayName ?? metadata.PropertyName ?? htmlFieldName.Split('.').Last();
if (String.IsNullOrEmpty(labelText))
{
return MvcHtmlString.Empty;
}

TagBuilder tag = new TagBuilder("label");
tag.Attributes.Add("for", html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(htmlFieldName));
tag.SetInnerText(labelText);
return MvcHtmlString.Create(tag.ToString(TagRenderMode.Normal));
}
}

我的示例模型:

public class Parent
{
public object Child { get; set; }
}

[DisplayName("yo")]
public class Child
{
public int Id { get; set; }
}

查看:

@Html.LabelForCustom(m => m.Child)  @*prints yo*@

关于c# - Html.Label 用于使用对象的 DisplayName 而不是属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15968305/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com