使用DropDownListFor()/ EditorFor()在MVC视图上设置TAB顺序?

时间:2015-12-31 15:18:05

标签: asp.net-mvc razor asp.net-mvc-5 tab-ordering

从视觉上讲,在我的一个MVC视图中,我有大约20个标准垂直顺序的字段,前8个字段在右侧的同一<div>组中有可选的[创建]框。

我的默认标签顺序目前点击我的第一个下拉列表,然后右键进入[创建],一直到下一个,然后右键等等。我想做的事情将TAB顺序设置为直接向下我的各个字段并将[Create]框保留为用户可选(或在Tab键顺序的末尾)。虽然似乎有很多关于快速搜索的讨论,但似乎答案不一致;很多人似乎在几年前关于在EditorFor()中设置TAB订单但被迫使用自定义编辑器模板或切换到TextBoxFor()

希望有人可以权衡这一点。下面详细介绍了我的字段:

(8 of these DropDownListFor()):
@Html.DropDownListFor(model => model.STATUS_ID, (SelectList)ViewBag.Model_List, htmlAttributes: new { @class = "form-control dropdown", @id = "selectStatus" })

(12 of these EditorFor()):
@Html.EditorFor(model => model.NOTE, new { htmlAttributes = new { @class = "form-control" } })

1 个答案:

答案 0 :(得分:3)

要设置Tab键顺序,您只需要在生成的字段中添加额外的属性tabindex即可。使用TextBoxForDropDownListFor之类的内容非常简单,因为它们实际上专门为此目的采用htmlAttributes参数:

@Html.TextBoxFor(m => m.Foo, new { tabindex = 1 })

过去,EditorFor也不能说同样的话。因为它是一个模板化的&#34;帮助器,编辑器模板,而不是方法调用,影响生成的内容。你可以在EditorFor的定义中看到这一点,因为其他帮助者没有htmlAttributes param,而是additionalViewData

从MVC 5.1开始,Microsoft可以通过特别命名的EditorFor密钥ViewData将其他HTML属性传递给"htmlAttributes"。因此,您可以实现与使用TextBoxFor之类的功能相同的功能,尽管它有点冗长:

@Html.EditorFor(m => m.Foo, new { htmlAttributes = new { tabindex = 1 } })

请注意,您实际上仍在此处传递additionalViewData,但其他视图数据包含一个键入htmlAttributes的匿名对象。然后,内置编辑器模板知道如何利用ViewData["htmlAttributes"]向生成的元素添加其他属性。但是,这仅适用于默认编辑器模板,因为Microsoft已专门对它们进行编程以使用它。只要您添加自己的自定义编辑器模板,就可以直接回到开始的位置。

您可以通过多种方式使用自定义编辑器模板来解决此问题。首先,您可以直接将选项卡索引作为视图数据传递,并在模板中使用它:

@Html.EditorFor(m => m.Foo, new { tabindex = 1 })

然后,在您的编辑器模板中:

@Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { tabindex = ViewData["tabindex"]})

其次,您可以使用默认模板模仿EditorFor的行为:

@Html.EditorFor(m => m.Foo, new { htmlAttributes = new { tabindex = 1 } })

然后,在您的编辑器模板中:

@Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, ViewData["htmlAttributes"])

但是,该选项不允许您使用&#34;默认&#34;属性。这是一种全有或全无的方法。要真正能够像内置编辑器模板一样使用ViewData["htmlAttributes"],您需要首先将默认属性与传入的属性相结合,然后将整个shebang传递给{{1} }。我有blog post that discusses that in depth,但有TL; DR:您需要以下扩展程序:

htmlAttributes

然后,您需要将以下内容添加到自定义编辑器模板的顶部:

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;
    }
}

您需要更改@{ var defaultHtmlAttributesObject = new { type = "date", @class = "form-control" }; var htmlAttributesObject = ViewData["htmlAttributes"] ?? new { }; var htmlAttributes = Html.MergeHtmlAttributes(htmlAttributesObject, defaultHtmlAttributesObject); } 变量,具体取决于默认情况下为特定模板生成的输入应具有的属性。