0

有没有办法将视图模型传递给 @helper 函数?

我有一个显示是/否/可能单选按钮的自定义编辑器。此编辑器的代码如下所示。由于它需要一个自定义函数加上 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>
4

1 回答 1

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(not ) 的命名空间标记中或通过添加指令~/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定义),它们不能是通用的,因此您将很难声明这样的构造。

于 2012-12-25T00:41:29.967 回答