通过视图模型属性向 MVC3 添加 data-* 属性

Adding data-* attributes to MVC3 through a view model attribute

提问人:rossisdead 提问时间:2/9/2012 最后编辑:rossisdead 更新时间:3/8/2013 访问量:3512

问:

我希望为我正在开发的网站创建一个不显眼的级联下拉系统。不过,我无法弄清楚如何让各种 HtmlHelper 方法将自定义 html 属性包含在呈现的标签中。

查看内置 HtmlHelper 方法的源代码,它们都调用了 GetUnobtrusiveValidationAttributes,这将创建所有 data-val-* html 属性。如果您需要验证器属性,那就太好了,但我希望能够以这种方式添加其他属性,而无需更改模板和创建新的 HtmlHelper 扩展。

这可能吗?我是否忽略了什么?

编辑

我知道所有 HtmlHelper 方法都有一个重载,该重载接受具有 html 属性的对象。如果可能的话,我试图避免这种情况。

编辑 2

我基本上希望这种情况发生:

public class ViewModel
{
    [Cascading(Action="/Controller/Action")]
    public int Action { get; set; }
}

然后让 HtmlHelpers 呈现如下:

<select data-action="/Controller/Action"></select>

但最好不必编写扩展方法来执行此操作。我制作自己的帮助程序方法没有问题,但我想知道我是否缺少一些已经查看随机模型元数据并可以添加 html 属性的内置功能。

asp.net-mvc-3 不显眼的javascript

评论


答:

2赞 Joel Purra 2/9/2012 #1

看到编辑 1+2,我认为您需要创建自己的扩展。由于您正在处理下拉列表,因此可以查看此实现,但通过 IMetadataAware 使用自定义属性

IMetadataAware:此接口可由属性类实现,以便属性可以将元数据添加到模型元数据创建过程中,而无需编写自定义元数据提供程序。此接口由 AssociatedMetadataProvider 类使用,因此此行为由派生自它的所有类(如 DataAnnotationsModelMetadataProvider 类)继承。


这部分不再作为答案

如果要将自定义属性添加到生成的 HTML 中,可以使用许多帮助程序上可用的参数,例如在 @Html.ActionLink() 中。Object htmlAttributes

具有自定义属性的示例,这些属性可用于不显眼地启动模式对话框,用于在启用 javascript 的客户端上编辑用户设置。Bootstrap 的模态使用与此类似的东西。data-*

请注意,我使用下划线而不是破折号作为数据属性

@Html.ActionLink(
    "Settings",
    "CreateOrUpdate",
    "User",
    new { id = "1234" },
    new {
        title = "Edit your personal settings", 
        data_show_modal = "#my-user-settings-modal"
    })

在您的情况下,我猜您正在使用 @Html.DropDownList(...),这也需要。随心所欲地填充它们,让你的 javascript 选择正确的属性。htmlAttributesdata-*

public static MvcHtmlString DropDownList(
    this HtmlHelper htmlHelper,
    string name,
    IEnumerable<SelectListItem> selectList,
    string optionLabel,
    Object htmlAttributes
)

评论

0赞 rossisdead 2/9/2012
谢谢,不过,我尽量避免手动添加所有这些值。我希望 html 属性来自我正在创建的视图模型属性。
0赞 Joel Purra 2/9/2012
哦,一定是错过了标题中的那部分。
0赞 rossisdead 2/9/2012
不用担心,其他人发布了相同的答案,然后将其删除。我更新了我的问题,使其更清晰一些。
0赞 rossisdead 2/11/2012
我已经接受了这个答案,因为这几乎是我最终不得不做的。
0赞 linkerro 2/9/2012 #2

如果不使用编辑器/显示模板或 HtmlAttributes,就无法做到这一点。

这些模板的优点是,您可以在一个位置轻松添加标记,并让它们传播到整个应用程序。

0赞 ProfK 3/8/2013 #3

我使用派生属性将属性从视图模型传递到编辑器模板,以及我昨天才知道的精彩界面1UIHintIMetadataAware

请注意,对基构造函数的调用如何强制使用我编写的编辑器模板的名称,特别是将属性作为参数添加到实际帮助程序中。传递给参数的常量等于编辑器模板的名称“SelectionOtherInput”。KnownUiHints.SelectionOtherUIHint

然后,帮助程序参数可供帮助程序代码使用。

例如,My 使用以下代码传达属性:DropDownAttribute

public class SelectionOtherInputAttribute : UIHintAttribute, IMetadataAware
{
    public SelectionOtherInputAttribute(string selectionElementName) : base(KnownUiHints.SelectionOther, KnownPresentationLayers.Mvc)
    {
        SelectionElementName = selectionElementName;
    }
    public SelectionOtherInputAttribute(string selectionElementName, object otherSelectionKey) : base(KnownUiHints.SelectionOther, KnownPresentationLayers.Mvc)
    {
        SelectionElementName = selectionElementName;
        ControlParameters[SelectionOtherInputControlParameterKeys.OtherSelectionKey] = otherSelectionKey;
    }
    public string SelectionElementName { get; set; }
    public object OtherSelectionKey { get; set; }
    public void OnMetadataCreated(ModelMetadata metadata)
    {
        metadata.AdditionalValues["@OtherSelectionAttrinbuteNames.SelectionElementName"] = SelectionElementName;
        metadata.AdditionalValues["@OtherSelectionAttrinbuteNames.OtherSelectionKey"] = OtherSelectionKey;
    }
}

这是我的编辑器模板。SelectionOtherInput

@using OtherInput.Core
@{
    var meta = ViewData.ModelMetadata.AdditionalValues;
    var selectionElementName = (string)meta["@OtherSelectionAttrinbuteNames.SelectionElementName"];
    var otherSelectionKey = meta["@OtherSelectionAttrinbuteNames.OtherSelectionKey"];
    var inputElementname = ViewData.TemplateInfo.HtmlFieldPrefix;
}
@Html.SelectionOtherTextBoxFor(m => Model, selectionElementName, otherSelectionKey.ToString())

然后,我在视图模型中使用我的属性,如下所示:

[SelectionOtherInput("EmploymentStatusId", 1)]
public string OtherEmploymentStatus { get; set; }

这会导致编辑器模板呈现,而编辑器模板又呈现我的帮助程序,其属性作为参数传递。OtherEmploymentStatusSelectionOtherInputSelectionOtherTextBoxFor