什么是 HtmlHelper 呈现 htmlAttributes 对象的方法?

Dim*_*ima 5 asp.net-mvc mvc-editor-templates razor

我正在构建一个编辑器模板,它将接受htmlAttributes对象。

例子很简单。

在主视图中,我有类似的东西

@Html.EditorFor(Function(x) x.SomeProperty, New With {.htmlAttributes = New With {.class = "form-control"}}). 
Run Code Online (Sandbox Code Playgroud)

在编辑器模板中,我需要class="form-control"编写属性。

如果在模板中我使用了类似的东西@Html.TextBoxFor(Function(x) x, ViewData("htmlAttributes")),那么一切都很好。但是如果我手动构建一个标签,我没有办法输出htmlAttributes,即我构建<input type="text" {htmlAttributes should be here} />

是否有任何公共方法可以正确呈现标签内的 HTML 属性?

Chr*_*att 5

我不确定你在这里寻找什么。传统上,编辑器模板只会传递 htmlAttributes。例如:

看法

@Html.EditorFor(m => m.FooString, new { htmlAttributes = new { @class = "foo" } })
Run Code Online (Sandbox Code Playgroud)

字符串.cshtml

@Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue.ToString(), ViewData["htmlAttributes"])
Run Code Online (Sandbox Code Playgroud)

如果您询问如何执行诸如设置默认值之类的操作,然后可以通过传递htmlAttributes. 然后,您几乎可以自己在那里。MVC 中没有任何东西可以帮助您(至少完全)。但是,我确实编写了自己的 HtmlHelper 扩展来处理这个问题。我实际上写了一篇博客文章来解释它的作用以及如何使用它。我建议你检查一下,但为了完整起见,我会在这里发布代码。

using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;

public static partial class HtmlHelperExtensions
{
    public static IDictionary<string, object> MergeHtmlAttributes(this HtmlHelper helper, object htmlAttributesObject, object defaultHtmlAttributesObject)
    {
        var concatKeys = new string[] { "class" };

        var htmlAttributesDict = htmlAttributesObject as IDictionary<string, object>;
        var defaultHtmlAttributesDict = defaultHtmlAttributesObject as IDictionary<string, object>;

        RouteValueDictionary htmlAttributes = (htmlAttributesDict != null)
            ? new RouteValueDictionary(htmlAttributesDict)
            : HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributesObject);
        RouteValueDictionary defaultHtmlAttributes = (defaultHtmlAttributesDict != null)
            ? new RouteValueDictionary(defaultHtmlAttributesDict)
            : HtmlHelper.AnonymousObjectToHtmlAttributes(defaultHtmlAttributesObject);

        foreach (var item in htmlAttributes)
        {
            if (concatKeys.Contains(item.Key))
            {
                defaultHtmlAttributes[item.Key] = (defaultHtmlAttributes[item.Key] != null)
                    ? string.Format("{0} {1}", defaultHtmlAttributes[item.Key], item.Value)
                    : item.Value;
            }
            else
            {
                defaultHtmlAttributes[item.Key] = item.Value;
            }
        }

        return defaultHtmlAttributes;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,在您的编辑器模板中(Date.cshtml在本例中):

@{
    var defaultHtmlAttributesObject = new { type = "date", @class = "form-control" };
    var htmlAttributesObject = ViewData["htmlAttributes"] ?? new { };
    var htmlAttributes = Html.MergeHtmlAttributes(htmlAttributesObject, defaultHtmlAttributesObject);
}
@Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue.ToString(), htmlAttributes)
Run Code Online (Sandbox Code Playgroud)

更新

我不能使用@Html.TextBox,但需要手动编写 <input type="text" {htmlAttributes should be here} />

为什么?没有什么是你不能用辅助版本做的。然而,如果你坚持走这条路,你将很难用 Razor 做到这一点。假设您实际上可以在没有 Razor 语法错误的情况下编写它,那么代码将是虚拟不可读的。我建议使用TagBuilder和/或StringBuilder在纯 C# 中构造一个字符串,然后确保您返回/设置一个类型的变量MvcHtmlString

var output = new MvcHtmlString(builder.ToString());
Run Code Online (Sandbox Code Playgroud)

但是,如果你走那么远,它就否定了使用编辑器模板的目的,除非你试图覆盖默认的编辑器模板之一。无论如何,我建议您只创建自己的 HtmlHelper 扩展,然后直接在您的视图中使用它或在您的编辑器模板中使用它。


teo*_*kot 5

对于您的情况,您可以使用静态方法来帮助您序列化为您需要的htmlAttributes内容。string我认为这就是你所需要的:

public static string StringlifyHtmlAttributes(object htmlAttributes)
{
    string stringHtmlAttributes = String.Empty;
    foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(htmlAttributes))
    {
        stringHtmlAttributes += string.Format("{0}=\"{1}\" ", property.Name.Replace('_', '-'), property.GetValue(htmlAttributes));
    }
    return stringHtmlAttributes;
}
Run Code Online (Sandbox Code Playgroud)