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

时间:2012-02-09 14:18:48

标签: asp.net-mvc-3 unobtrusive-javascript

我正在寻找为我正在开发的网站创建一个不显眼的级联下拉系统。我无法弄清楚如何让各种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属性。

3 个答案:

答案 0 :(得分:2)

看到编辑1 + 2,我认为你需要创建自己的扩展。由于您是dealing with dropdowns,因此have a look at this implementation可以use custom attributes via IMetadataAware

  

IMetadataAware:此接口可以由属性类实现,以便属性可以在不编写自定义元数据提供程序的情况下将元数据添加到模型元数据创建过程。此接口由AssociatedMetadataProvider类使用,因此所有从其派生的类(例如DataAnnotationsModelMetadataProvider类)都会继承此行为。


此部分不再有用作为答案

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

自定义data-*属性的示例,可用于不显眼地启动模式对话框,以便在启用javascript的客户端上编辑用户设置。 Bootstrap's modal使用与此类似的内容。

请注意,我using underscores instead of dashes for the data attribute

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

在您的情况下,我猜您使用的是@Html.DropDownList(...),也需要htmlAttributes。根据需要填充它们,让您的javascript选择正确的data-*属性。

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

答案 1 :(得分:0)

如果不使用编辑器/显示模板或HtmlAttributes,则无法执行此操作。

模板具有以下优势:您可以在一个位置轻松添加标签,并让它们在整个应用程序中传播。

答案 2 :(得分:0)

我使用UIHint派生属性将视图模型中的属性传递给编辑器模板,其中只有昨天才知道的精彩IMetadataAware接口 1

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

辅助参数随后可用于帮助程序代码。

E.g。我的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; }

这导致OtherEmploymentStatus SelectionOtherInputSelectionOtherTextBoxFor编辑器模板呈现,该模板反过来呈现我的{{1}}帮助器,其属性作为参数传递。