有没有办法将视图模型传递给@helper函数?
我有一个自定义编辑器,显示Yes / No / Maybe单选按钮。该编辑器的代码如下所示。由于它需要一个自定义函数加上3行代码来显示每个单选按钮,我想封装在全局@helper函数中创建每个单选按钮及其相关标签的代码,但我无法弄清楚如何将RadioButtonFor移动到全局辅助函数中。
鲍勃
这是现有代码:
@model System.String
@functions {
// Returns an anonymous object that specifies the radio button HTML options
private object HTMLOptions(string id, bool @checked) {
if (@checked) {
return new { id, @checked = "checked" };
} else {
return new { id };
}
}
}
@{
string value = Model + "";
string id;
}
<div class="option-list">
@{id = ViewData.TemplateInfo.GetFullHtmlFieldId("radioYes");}
@Html.RadioButtonFor(q => q, "true", HTMLOptions(id, value == "true"))
@Html.LabelFor(q => q, "Yes", new {@for = id})
<br />
@{id = ViewData.TemplateInfo.GetFullHtmlFieldId("radioNo");}
@Html.RadioButtonFor(q => q, "false", HTMLOptions(id, value == "false"))
@Html.LabelFor(q => q, "No", new {@for = id})
<br />
@{id = ViewData.TemplateInfo.GetFullHtmlFieldId("radioMaybe");}
@Html.RadioButtonFor(q => q, "maybe", HTMLOptions(id, value == "maybe"))
@Html.LabelFor(q => q, "Maybe", new {@for = id})
<br />
</div>
我希望能够在一次调用中编写一个封装RadioButtonFor和LabelFor的通用助手,以及我的附加代码以包含“checked”属性,如下所示:
@model something
<div class="option-list">
@MyRadioButtonAndLabelFor(q => something.x, "Yes", "true") @* (model, label, value) *@
@MyRadioButtonAndLabelFor(q => something.x, "No", "false")
@MyRadioButtonAndLabelFor(q => something.x, "Maybe", "maybe")
</div>
答案 0 :(得分:2)
试试这样:
@model System.String
@functions {
private object HtmlAttributes(string id, string model, string value) {
if (model == value) {
return new { id, @checked = "checked" };
}
return new { id };
}
}
@helper Radios(HtmlHelper<string> html) {
var model = html.ViewData.Model;
@html.RadioButtonFor(q => q, "true", HtmlAttributes("yes", model, "true"))
@Html.LabelFor(q => q, "Yes", new { @for = "yes" })
<br/>
@html.RadioButtonFor(q => q, "false", HtmlAttributes("no", model, "false"))
@Html.LabelFor(q => q, "No", new { @for = "no" })
<br/>
@html.RadioButtonFor(q => q, "maybe", HtmlAttributes("maybe", model, "maybe"))
@Html.LabelFor(q => q, "Maybe", new { @for = "maybe" })
<br/>
}
<div class="option-list">
@Radios(Html)
</div>
击> <击> 撞击>
更新:
似乎我误解了你的问题。更新后,我更了解您要实现的目标。为了实现它,你可以编写一个自定义的Html帮助器:
using System;
using System.Linq.Expressions;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;
public static class HtmlExtensions
{
public static IHtmlString MyRadioButtonAndLabelFor<TModel, TValue>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TValue>> expression,
string label,
object value
)
{
var name = ExpressionHelper.GetExpressionText(expression);
var id = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(
name + value
);
var sb = new StringBuilder();
sb.Append(htmlHelper.RadioButtonFor(expression, value, new { id = id }));
var labelTag = new TagBuilder("label");
labelTag.SetInnerText(label);
labelTag.Attributes["for"] = id;
sb.Append(labelTag.ToString());
return new HtmlString(sb.ToString());
}
}
然后你可以有一个视图模型:
public class MyViewModel
{
public string Value { get; set; }
}
控制器:
public class HomeController : Controller
{
public ActionResult Index()
{
return View(new MyViewModel
{
Value = "false"
});
}
}
和相应的观点:
@model MyViewModel
<div class="option-list">
@Html.MyRadioButtonAndLabelFor(q => q.Value, "Yes", "true")
@Html.MyRadioButtonAndLabelFor(q => q.Value, "No", "false")
@Html.MyRadioButtonAndLabelFor(q => q.Value, "Maybe", "maybe")
</div>
备注:为了将MyRadioButtonAndLabelFor
自定义扩展方法引入范围,您需要添加名称空间,其中包含的类(HtmlExtensions
)已在您的命名空间标记中声明~/Views/web.config
(不是~/web.config
)或在视图中添加@using ...
指令。
如果您愿意,还可以在Razor视图中定义内联帮助:
@functions {
public IHtmlString MyRadioButtonAndLabelFor<TModel, TValue>(
HtmlHelper<TModel> htmlHelper,
System.Linq.Expressions.Expression<Func<TModel, TValue>> expression,
string label,
object value
)
{
var name = ExpressionHelper.GetExpressionText(expression);
var id = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(name + value);
var sb = new StringBuilder();
sb.Append(htmlHelper.RadioButtonFor(expression, value, new { id = id }));
var labelTag = new TagBuilder("label");
labelTag.SetInnerText(label);
labelTag.Attributes["for"] = id;
sb.Append(labelTag.ToString());
return new HtmlString(sb.ToString());
}
}
然后像这样使用它:
<div class="option-list">
@MyRadioButtonAndLabelFor(Html, q => q.Value, "Yes", "true")
@MyRadioButtonAndLabelFor(Html, q => q.Value, "No", "false")
@MyRadioButtonAndLabelFor(Html, q => q.Value, "Maybe", "maybe")
</div>
就Razor助手而言(@helper
定义),嗯,他们不能是通用的,因此你将有麻烦宣布这样的结构。