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」属性を含めるための追加コードを 1 回の呼び出しで記述できるようにしたいと考えています。

@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~/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 に答える