MVC3剃刀扩展:返回两个控件

时间:2011-11-21 16:22:26

标签: c# asp.net-mvc-3 razor

我正在尝试创建一个呈现只读下拉列表的扩展名。看来只是在readonly="true"元素上打一个<select>属性不起作用,所以我想渲染一个禁用的<select>元素和一个隐藏的输入。

这是我到目前为止的代码:

public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
    Expression<Func<TModel, TProperty>> expression,
    IEnumerable<SelectListItem> selectList,
    object htmlAttributes,
    bool isReadonly)
{
    var values = new RouteValueDictionary(htmlAttributes);
    if (isReadonly) values["disabled"] = "disabled";

    var select = htmlHelper.DropDownListFor<TModel, TProperty>(expression, selectList, values);
    var hiddenField = htmlHelper.HiddenFor<TModel, TProperty>(expression);
    var bothFields = ?;

    return bothFields;
}

从Razor扩展中渲染多个控件的正确方法是什么?

已编辑:解决方案

想出来。显然你可以在两个元素上调用ToString()并返回它。正如Jerad指出的那样,<select>的id必须被修改,因此它与隐藏输入的id不同。我的最终代码如下所示:

public static MvcHtmlString DropDownListFor<TModel, TProperty>(
    this HtmlHelper<TModel> htmlHelper,
    Expression<Func<TModel, TProperty>> expression,
    IEnumerable<SelectListItem> selectList,
    object htmlAttributes,
    bool isReadonly)
{
    if (isReadonly)
    {
        var values = new RouteValueDictionary(htmlAttributes);
        values["disabled"] = "disabled";
        values["id"] = (expression.Body as MemberExpression).Member.Name + "_Disabled";

        var select = htmlHelper.DropDownListFor<TModel, TProperty>(expression, selectList, values);
        var hiddenField = htmlHelper.HiddenFor<TModel, TProperty>(expression);
        return new MvcHtmlString(select.ToString() + hiddenField.ToString());
    }
    else
    {
        return htmlHelper.DropDownListFor<TModel, TProperty>(expression, selectList, htmlAttributes);
    }
}

1 个答案:

答案 0 :(得分:1)

我认为最好的方法是使用一个EditorTemplate来渲染这两个字段 - 从我所看到的HtmlHelper扩展,扩展方法通常会返回一个HTML控件。

例如,在您的视图中:

@Html.EditorFor(m => m.SomeField, "ReadOnlyDropDown")

在你的编辑器模板中:

@Html.DropDownListFor(m => m, mySelectList, null, true)
@Html.HiddenFor(m => m)

另外,您的表单上最终会出现名称冲突,不是吗?看起来隐藏和选择元素都将使用相同的名称进行渲染。

如果你真的想把这两者合二为一,我想你可以简单地连接两个HTML元素的结果,因为这些只是MvcHtmlString对象:

var bothFields = select + hidden;