我正在尝试创建一个呈现只读下拉列表的扩展名。看来只是在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);
}
}
答案 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;