Hat jemand RadioButtonListFor <T> für ASP.NET MVC implementiert?


75

Html.RadioButtonListIn ASP.NET MVC Futures gab es eine Erweiterungsmethode. Hat jemand einen Code für eine stark typisierte Version gefunden RadioButtonListFor<T>. In einer Ansicht würde es so aussehen:

<%= Html.RadioButtonListFor(model=>model.Item,Model.ItemList) %>

1
Es gibt eine mit Ajax-Funktionalität hier: awesome.codeplex.com
Omu

Antworten:


88

Hier ist die Verwendung auf der Aspx-Seite

    <%= Html.RadioButtonListFor(m => m.GenderRadioButtonList)%>

Hier ist das Ansichtsmodell

public class HomePageViewModel
{
    public enum GenderType
    {
        Male,
        Female
    }
    public RadioButtonListViewModel<GenderType> GenderRadioButtonList { get; set; }

    public HomePageViewModel()
    {
        GenderRadioButtonList = new RadioButtonListViewModel<GenderType>
        {
            Id = "Gender",
            SelectedValue = GenderType.Male,
            ListItems = new List<RadioButtonListItem<GenderType>>
            {
                new RadioButtonListItem<GenderType>{Text = "Male", Value = GenderType.Male},
                new RadioButtonListItem<GenderType>{Text = "Female", Value = GenderType.Female}
            }
        };
    }
}

Hier ist das Ansichtsmodell, das für Optionsfeldlisten verwendet wird

public class RadioButtonListViewModel<T>
{
    public string Id { get; set; }
    private T selectedValue;
    public T SelectedValue
    {
        get { return selectedValue; }
        set
        {
            selectedValue = value;
            UpdatedSelectedItems();
        }
    }

    private void UpdatedSelectedItems()
    {
        if (ListItems == null)
            return;

        ListItems.ForEach(li => li.Selected = Equals(li.Value, SelectedValue));
    }

    private List<RadioButtonListItem<T>> listItems;
    public List<RadioButtonListItem<T>> ListItems
    {
        get { return listItems; }
        set
        {
            listItems = value;
            UpdatedSelectedItems();
        }
    }
}

public class RadioButtonListItem<T>
{
    public bool Selected { get; set; }

    public string Text { get; set; }

    public T Value { get; set; }

    public override string ToString()
    {
        return Value.ToString();
    }
}

Hier sind die Erweiterungsmethoden für RadioButtonListFor

public static class HtmlHelperExtensions
{
    public static string RadioButtonListFor<TModel, TRadioButtonListValue>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, RadioButtonListViewModel<TRadioButtonListValue>>> expression) where TModel : class
    {
        return htmlHelper.RadioButtonListFor(expression, null);
    }

    public static string RadioButtonListFor<TModel, TRadioButtonListValue>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, RadioButtonListViewModel<TRadioButtonListValue>>> expression, object htmlAttributes) where TModel : class
    {
        return htmlHelper.RadioButtonListFor(expression, new RouteValueDictionary(htmlAttributes));
    }

    public static string RadioButtonListFor<TModel, TRadioButtonListValue>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, RadioButtonListViewModel<TRadioButtonListValue>>> expression, IDictionary<string, object> htmlAttributes) where TModel : class
    {
        var inputName = GetInputName(expression);

        RadioButtonListViewModel<TRadioButtonListValue> radioButtonList = GetValue(htmlHelper, expression);

        if (radioButtonList == null)
            return String.Empty;

        if (radioButtonList.ListItems == null)
            return String.Empty;

        var divTag = new TagBuilder("div");
        divTag.MergeAttribute("id", inputName);
        divTag.MergeAttribute("class", "radio");
        foreach (var item in radioButtonList.ListItems)
        {
            var radioButtonTag = RadioButton(htmlHelper, inputName, new SelectListItem{Text=item.Text, Selected = item.Selected, Value = item.Value.ToString()}, htmlAttributes);

            divTag.InnerHtml += radioButtonTag;
        }

        return divTag + htmlHelper.ValidationMessage(inputName, "*");
    }

    public static string GetInputName<TModel, TProperty>(Expression<Func<TModel, TProperty>> expression)
    {
        if (expression.Body.NodeType == ExpressionType.Call)
        {
            var methodCallExpression = (MethodCallExpression)expression.Body;
            string name = GetInputName(methodCallExpression);
            return name.Substring(expression.Parameters[0].Name.Length + 1);

        }
        return expression.Body.ToString().Substring(expression.Parameters[0].Name.Length + 1);
    }

    private static string GetInputName(MethodCallExpression expression)
    {
        // p => p.Foo.Bar().Baz.ToString() => p.Foo OR throw...

        var methodCallExpression = expression.Object as MethodCallExpression;
        if (methodCallExpression != null)
        {
            return GetInputName(methodCallExpression);
        }
        return expression.Object.ToString();
    }

    public static string RadioButton(this HtmlHelper htmlHelper, string name, SelectListItem listItem,
                         IDictionary<string, object> htmlAttributes)
    {
        var inputIdSb = new StringBuilder();
        inputIdSb.Append(name)
            .Append("_")
            .Append(listItem.Value);

        var sb = new StringBuilder();

        var builder = new TagBuilder("input");
        if (listItem.Selected) builder.MergeAttribute("checked", "checked");
        builder.MergeAttribute("type", "radio");
        builder.MergeAttribute("value", listItem.Value);
        builder.MergeAttribute("id", inputIdSb.ToString());
        builder.MergeAttribute("name", name + ".SelectedValue");
        builder.MergeAttributes(htmlAttributes);
        sb.Append(builder.ToString(TagRenderMode.SelfClosing));
        sb.Append(RadioButtonLabel(inputIdSb.ToString(), listItem.Text, htmlAttributes));
        sb.Append("<br>");

        return sb.ToString();
    }

    public static string RadioButtonLabel(string inputId, string displayText,
                                 IDictionary<string, object> htmlAttributes)
    {
        var labelBuilder = new TagBuilder("label");
        labelBuilder.MergeAttribute("for", inputId);
        labelBuilder.MergeAttributes(htmlAttributes);
        labelBuilder.InnerHtml = displayText;

        return labelBuilder.ToString(TagRenderMode.Normal);
    }


    public static TProperty GetValue<TModel, TProperty>(HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression) where TModel : class
    {
        TModel model = htmlHelper.ViewData.Model;
        if (model == null)
        {
            return default(TProperty);
        }
        Func<TModel, TProperty> func = expression.Compile();
        return func(model);
    }
}

2
Ich denke, Keltex hat es vielleicht eher im Antwortbeitrag als im Blog gemeint. Ich gehe kaum auf eine Website eines Drittanbieters und lade die Quelle herunter, aber ich schaue mir gerne Codebeispiele der Kernabschnitte hier oder sogar im Blog an :)
Jay,

Oh ich verstehe. Ich habe damit angefangen, aber der Code wurde verrückt groß, also dachte ich, dass es sich nicht lohnt, ihn zu wiederholen. Ich kann sehen, dass das Posten von Code-Schnipsel nützlich wäre, aber das Posten der 4-5 Klassen, die in diesem Fall benötigt werden, könnte übertrieben sein. Trotzdem kann ich das tun, wenn es das ist, was gewünscht wird. Gedanken?
Mac

Menschen auf SO scheinen lange Antworten nicht zu stören , solange sie beschreibend sind ( ein Beispiel finden Sie unter stackoverflow.com/questions/1863884/which-orm-supports-this/… ). Abgesehen davon glaube ich, dass Sie den Code aus meiner Antwort unten auf ~ 40 Zeilen reduzieren könnten, wenn Sie nur Optionsfelder anstelle der verschiedenen Eingabetypen verwenden möchten, und ich bin sicher, dass Sie dasselbe mit Ihrem tun könnten . Fühlen Sie sich frei, den Code in meiner Antwort zu verwenden, wenn es einfacher ist :)
Jay

Ist es ein konsistenter Ansatz, das oben genannte MVVM-Muster in einer MVC-Anwendung zu verwenden?
mirezus

9
Dies scheint mit MVC2 nicht zu funktionieren, da es einen htmlHelper.ValidationMessagezurückgibt, MvcHtmlStringder den +Operator für Zeichenfolgen nicht implementiert .
Drew Noakes

26

MVC 3-Beispiel, das 3 Optionsfelder mit Validierung erstellt, um sicherzustellen, dass 1 Option ausgewählt ist. Wenn die Validierung des Formulars fehlschlägt (z. B. in anderen Feldern), wird die ausgewählte Funkoption beim erneuten Anzeigen des Formulars vorausgewählt.

Aussicht

@Html.RadioButtonForSelectList(m => m.TestRadio, Model.TestRadioList)
@Html.ValidationMessageFor(m => m.TestRadio)

Modell

public class aTest
{
    public Int32 ID { get; set; }
    public String Name { get; set; }
}

public class LogOnModel
{
    public IEnumerable<SelectListItem> TestRadioList { get; set; }

    [Required(ErrorMessage="Test Error")]
    public String TestRadio { get; set; }

    [Required]
    [Display(Name = "User name")]
    public string UserName { get; set; }
}

Controller-Aktionen

public ActionResult LogOn()
    {
        List<aTest> list = new List<aTest>();
        list.Add(new aTest() { ID = 1, Name = "Line1" });
        list.Add(new aTest() { ID = 2, Name = "Line2" });
        list.Add(new aTest() { ID = 3, Name = "Line3" });

        SelectList sl = new SelectList(list, "ID", "Name");

        var model = new LogOnModel();
        model.TestRadioList = sl;

        return View(model);
    }

    [HttpPost]
    public ActionResult LogOn(LogOnModel model, string returnUrl)
    {
        if (ModelState.IsValid)
        {
             ....
        }

        // If we got this far, something failed, redisplay form
        List<aTest> list = new List<aTest>();
        list.Add(new aTest() { ID = 1, Name = "Line1" });
        list.Add(new aTest() { ID = 2, Name = "Line2" });
        list.Add(new aTest() { ID = 3, Name = "Line3" });

        SelectList sl = new SelectList(list, "ID", "Name");
        model.TestRadioList = sl;

        return View(model);
    }

Hier ist die Erweiterung:

public static class HtmlExtensions
{
    public static MvcHtmlString RadioButtonForSelectList<TModel, TProperty>(
        this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TProperty>> expression,
        IEnumerable<SelectListItem> listOfValues)
    {
        var metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
        var sb = new StringBuilder();

        if (listOfValues != null)
        {
            foreach (SelectListItem item in listOfValues)
            {
                var id = string.Format(
                    "{0}_{1}",
                    metaData.PropertyName,
                    item.Value
                );

                var radio = htmlHelper.RadioButtonFor(expression, item.Value, new { id = id }).ToHtmlString();
                sb.AppendFormat(
                    "<label for=\"{0}\">{1}</label> {2}",
                    id,
                    HttpUtility.HtmlEncode(item.Text),
                    radio
                );
            }
        }

        return MvcHtmlString.Create(sb.ToString());
    }
}

Hat das Aussehen Ihrer Lösung am besten gefallen, sie sehr einfach integriert und funktioniert hervorragend, danke!
Baconbeastnz

Hallo dies nicht funktioniert, wenn eine Tabelle / grid rowwie Zeile hinzufügen Tabelle wird dynamisch an einem Tisch in der Client - Ansicht hinzugefügt unter Verwendung eines Klons. Bei der POST-Aktion ist das Optionsfeld für diese Zeile immer leer, aber die anderen Zellen kommen durch !!
Transformator

2

Okay, ich bin mir bewusst, dass dies keine direkte Antwort auf Ihre Frage ist, aber dies ist möglicherweise eine bessere Möglichkeit, die meisten Eingaben zu machen (und es hat Spaß gemacht, sie zu machen). Ich habe dies gerade erst abgeschlossen und einige Tests durchgeführt, daher kann ich nicht dafür bürgen, dass dies in jeder Situation perfekt ist.

Ich habe diese Idee von Jimmy Bogards Post hier bekommen . Schauen Sie mal rein, denn dort gibt es eine Menge wirklich cooler Ideen.

Was ich getan habe, ist ein "InputFor" -Helfer, der sein Bestes versucht, um herauszufinden, welche Eingabe Sie verlangen, und sie entsprechend ausgibt. Dies führt zu Optionsfeldern, standardmäßig jedoch zu einem Dropdown-Menü, wenn mehr als zwei vorhanden sind. Sie sollten diese Funktionalität problemlos ändern können.

Mit dem folgenden Code können Sie Anrufe wie <%= Html.InputFor(m => m.Gender) %>oder tätigen <%Html.InputFor(m => m.Gender, Model.GenderList)%>. Am Ende gibt es ein cooles kleines bisschen, mit dem Sie konventionell codieren können, aber wir werden später darauf zurückkommen.

public static MvcHtmlString InputFor<TModel>(this HtmlHelper<TModel> helper, Expression<Func<TModel, object>> field, Dictionary<string, string> listing) where TModel : class
        {
            string property_name = GetInputName(field);
            PropertyDescriptor descriptor = TypeDescriptor.GetProperties(helper.ViewData.Model).Find(property_name, true);
            string property_type = descriptor.PropertyType.Name;
            var func = field.Compile();
            var value = func(helper.ViewData.Model);

            //Add hidden element if required
            if (descriptor.Attributes.Contains(new HiddenInputAttribute()))
            {
                return helper.Hidden(property_name, value);
            }

            if (property_type == "DateTime" || property_type == "Date")
            {
                return helper.TextBox(property_name, value, new { @class = "date_picker" });
            }
            if (listing != null)
            {
                if (listing.Count <= 2)
                {
                    //This is a good length for a radio button
                    string output = "";
                    foreach (KeyValuePair<string, string> pair in listing)
                    {
                        TagBuilder label = new TagBuilder("label");
                        label.MergeAttribute("for", property_name);
                        label.SetInnerText(pair.Value);
                        output += helper.RadioButton(property_name, pair.Key, (value == pair.Key)).ToHtmlString();
                        output += label.ToString();
                    }
                    return MvcHtmlString.Create(output);
                }
                else
                {
                    //too big for a radio button, lets make a drop down
                    return helper.DropDownList(property_name, new SelectList(listing, "Key", "Value"), value);
                }
            }
            else
            {
                if (property_type == "Boolean")
                {
                    listing = new Dictionary<string, string>();
                    listing.Add("true", "Yes");
                    listing.Add("false", "No");
                    SelectList select_values = new SelectList(listing, "Key", "Value", ((bool)value ? "Yes" : "No"));
                    return helper.DropDownList(property_name, select_values);
                }
                return helper.TextBox(property_name, value);
            }
        }

Kodierung durch Konvention

Der folgende Code ermöglicht dies unter Berücksichtigung der Konvention über die Konfiguration. Ein Beispiel hierfür ist, wenn Sie ein Modellobjekt haben, das die Eigenschaft enthält, die Sie auflisten möchten (Geschlecht), und ein Wörterbuch mit demselben Namen, dem jedoch "Liste" (GenderList) angehängt ist, diese Liste standardmäßig verwendet.

zB <%= Html.InputFor(m => m.Gender) %>kann eine vollständige Dropdown-Liste / Optionsfeldgruppe erstellt werden, aber diese Standardwerte können durch einen Anruf wie überschrieben werden<%= Html.InputFor(m => m.Gender, alternate_list) %>

public static MvcHtmlString InputFor<TModel>(this HtmlHelper<TModel> helper, Expression<Func<TModel, object>> field) where TModel : class
{
    string property_name = GetInputName(field) + "List";
    PropertyDescriptor list_descriptor = TypeDescriptor.GetProperties(helper.ViewData.Model).Find(property_name, true);
    Dictionary<string, string> listing = null;

    if (list_descriptor != null)
    {
        //Found a match for PropertyNameList, try to pull it out so we can use it
        PropertyInfo temp = helper.ViewData.Model.GetType().GetProperty(property_name);
        listing = (Dictionary<string, string>)temp.GetValue(helper.ViewData.Model, null);
    }
    return InputFor(helper, field, listing);
}

Nun ein kleiner Haftungsausschluss:

  • Dies ist nicht der schnellste Code der Welt (aufgrund der Reflexion und anderer Dinge). In meiner Situation ist dies nicht wirklich relevant, da alles benutzergesteuert ist, wenn Sie vorhaben, etwas Verrücktes zu tun.
  • Dieser Code steckt noch in den Kinderschuhen. Ich werde ihn in den nächsten Tagen eingehender testen und ergänzen, offen für Vorschläge zur Verbesserung des Codes.

Ich hoffe, dieser Code ist für jemanden nützlich. Ich weiß, dass ich ihn in den nächsten Wochen verwenden werde, um die Zeit zu verkürzen. Dies zu reduzieren, um nur das Optionsfeld zu aktivieren, sollte eine triviale Aufgabe sein, viel Glück :)

Jay


2

Basierend auf Jon Post , eine kleine Verbesserung, um die Optionsfeldliste als ul mit HTMLAttributtes zu generieren

public static MvcHtmlString RadioButtonListFor<TModel, TProperty>(
        this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TProperty>> expression,
        IEnumerable<SelectListItem> listOfValues,
        IDictionary<string, object> radioHtmlAttributes = null,
        string ulClass = null)
    {
        ModelMetadata metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);

        if (radioHtmlAttributes == null)
            radioHtmlAttributes = new RouteValueDictionary();

        TagBuilder ulTag = new TagBuilder("ul");
        if (!String.IsNullOrEmpty(ulClass))
            ulTag.MergeAttribute("class", ulClass);

        if (listOfValues != null)
        {
            // Create a radio button for each item in the list 
            foreach (SelectListItem item in listOfValues)
            {

                // Generate an id to be given to the radio button field 
                var id = string.Format("{0}_{1}", metaData.PropertyName, item.Value);

                if (!radioHtmlAttributes.ContainsKey("id"))
                    radioHtmlAttributes.Add("id", id);
                else
                    radioHtmlAttributes["id"] = id;

                // Create and populate a radio button using the existing html helpers 
                var label = htmlHelper.Label(id, HttpUtility.HtmlEncode(item.Text));
                var radio = htmlHelper.RadioButtonFor(expression, item.Value, radioHtmlAttributes).ToHtmlString();

                // Create the html string that will be returned to the client 
                // e.g. <input data-val="true" data-val-required="You must select an option" id="TestRadio_1" name="TestRadio" type="radio" value="1" /><label for="TestRadio_1">Line1</label> 
                ulTag.InnerHtml += string.Format("<li>{0}{1}</li>", radio, label);
            }
        }

        return MvcHtmlString.Create(ulTag.ToString(TagRenderMode.Normal));
    }

    public static MvcHtmlString RadioButtonListFor<TModel, TProperty>(
        this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TProperty>> expression,
        IEnumerable<SelectListItem> listOfValues,
        object radioHtmlAttributes = null,
        string ulClass = null)
    {
        return RadioButtonListFor<TModel, TProperty>(htmlHelper, expression, listOfValues, new RouteValueDictionary(radioHtmlAttributes), ulClass);
    }

1

Ich habe etwas Ähnliches in MVC 1.0 implementiert. Sehen Sie, ob dies für Sie hilfreich ist:

    public static string RadioButtonList2(this HtmlHelper _helper, string _name, IEnumerable<SelectListItem> _items, string _selectedValue, string _seperator)
    {
        return RadioButtonList2(_helper, _name, _items, _selectedValue, _seperator, null);
    }

    public static string RadioButtonList2(this HtmlHelper _helper, string _name, IEnumerable<SelectListItem> _items, string _selectedValue, string _seperator, IDictionary<string, object> _htmlAttributes)
    {
        StringBuilder _outputScript = new StringBuilder();

        foreach (var item in _items)
        {
            var optionField = new TagBuilder("input");
            optionField.MergeAttribute("name", _name);
            optionField.MergeAttribute("id", _name);
            optionField.MergeAttribute("class", _name);
            optionField.MergeAttribute("value", item.Value);
            optionField.MergeAttribute("type", "radio");

            // Check to see if it's checked
            if (item.Value == _selectedValue)
                optionField.MergeAttribute("checked", "checked");

            if (_htmlAttributes != null)
                optionField.MergeAttributes(_htmlAttributes);

            _outputScript.Append(optionField.ToString(TagRenderMode.SelfClosing));
            _outputScript.Append("<label style=\"display:inline;\">");
            _outputScript.Append(item.Text);
            _outputScript.Append("</label>" + _seperator);
        }

        return _outputScript.ToString();
    }

In der Steuerung können Sie das Ergebnis wie folgt zurückgeben:

        ViewData["GenderList"] = new SelectList(new[] { new { Value = "M", Text = "Male" }, new { Value = "F", Text = "Female" }, new { Value = "A", Text = "All" } }, "Value", "Text");

oder

        ViewData["GenderList"] = new SelectList(_resultFromSomeLinqQuery, "GenderID", "GenderName");

Und verwenden Sie es in der Ansicht wie folgt:

<%= Html.RadioButtonList2("Sex", ViewData["GenderList"] as SelectList, ViewData["SelectedSex"].ToString(), "&nbsp;")%>

Sie können auch ersetzen die &nbsp;mit <BR />ihnen in separaten Zeilen angezeigt werden soll .

Hoffe das hilft.

Grüße Naweed Akram naweed@xgeno.com


Leider ist dies nicht die Vorlagenversion, nach der ich gesucht habe.
Keltex

1

Hier ist eine etwas schlankere Antwort in der guten alten VB. Funktioniert für mich, ist aber keine vollständige Lösung.

<Extension()> _
Public Function RadioButtonListFor(Of TModel, TProperty)(ByVal htmlHelper As System.Web.Mvc.HtmlHelper(Of TModel), ByVal expression As System.Linq.Expressions.Expression(Of System.Func(Of TModel, TProperty)), ByVal selectList As System.Collections.Generic.IEnumerable(Of System.Web.Mvc.SelectListItem), ByVal htmlAttributes As Object) As System.Web.Mvc.MvcHtmlString
    'Return htmlHelper.DropDownListFor(expression, selectList, htmlAttributes)
    If selectList Is Nothing OrElse selectList.Count = 0 Then Return MvcHtmlString.Empty

    Dim divTag = New TagBuilder("div")
    divTag.MergeAttributes(New RouteValueDictionary(htmlAttributes))
    Dim name = CType(expression.Body, System.Linq.Expressions.MemberExpression).Member.Name
    Dim value = expression.Compile()(htmlHelper.ViewData.Model)
    Dim sb As New StringBuilder()

    For Each item In selectList
        sb.AppendFormat("<input id=""{0}_{1}"" type=""radio"" name=""{0}"" value=""{1}"" {2} />", name, item.Value, If(item.Value = value.ToString, """checked""", ""))
        sb.AppendFormat("<label for=""{0}_{1}"">{2}</label>", name, item.Value, item.Text)
    Next

    divTag.InnerHtml = sb.ToString

    Return MvcHtmlString.Create(divTag.ToString)

End Function

0

Ich habe die Mac-Lösung geändert und den Enum-Typ durch eine Datenbanktabelle ersetzt. Meine Tabelle lautet:

Geben Sie hier die Bildbeschreibung ein

In meiner Bewerbung miete ich ein Zimmer nach Geschlecht. Mein Modell mit GenderRadios-Eigenschaft:

public partial class Room
{
 public RadioButtonListViewModel GenderRadios { get; set; }
 //...
}

Im Raumcontroller bereite ich Radios vor:

   private void fillRadios(Room room)
    {         
        List<Gender> genders = fre.Genders.ToList();
        room.GenderRadios= new RadioButtonListViewModel();
        room.GenderRadios.ListItems = new List<RadioButtonListItem>();
        foreach (Gender gender in genders)
            room.GenderRadios.ListItems.Add(new RadioButtonListItem { Text = gender.Name, Value = gender.Id, Selected= (room.GenderId == gender.Id)});
    }

Schließlich verwende ich es in der Ansicht, um Raum zu schaffen:

<tr> 
<td>Gender</td>
   <%= Html.RadioButtonListFor(m => m.GenderRadios, "GenderRadiosForRoomCreate")%>         
</tr>

und für den Bearbeitungsraum:

<tr> 
<td>Gender</td>
    <%= Html.RadioButtonListFor(m => m.GenderRadios, "GenderRadiosForRoomEdit")%>         
</tr>

Erstellen Sie Raum HTML wird wie folgt aussehen:

<td id="GenderRadisoForRoomCreate_Container">
<input id="GenderRadisoForRoomCreate_Any" name="GenderRadisoForRoomCreate_value" value="1" type="radio"><label for="GenderRadisoForRoomCreate_Any">Any</label>
<input id="GenderRadisoForRoomCreate_Female" name="GenderRadisoForRoomCreate_value" value="2" type="radio"><label for="GenderRadisoForRoomCreate_Female">Female</label>
<input id="GenderRadisoForRoomCreate_Male" name="GenderRadisoForRoomCreate_value" value="3" type="radio"><label for="GenderRadisoForRoomCreate_Male">Male</label>
</td>

Wenn ein Raum erstellt wurde:

[HttpPost]
public ActionResult RoomCreate(Room room, FormCollection formValues, int? GenderRadiosForRoomCreate_value, int? SmokingRadiosForRoomCreate_value)
{
    room.GenderId = GenderRadiosForRoomCreate_value;
    room.SmokingId = SmokingRadiosForRoomCreate_value;
//...
}

Hier ist die Helferklasse:

public class RadioButtonListViewModel
{
    public int Id { get; set; }

    private int selectedValue;
    public int SelectedValue
    {
        get { return selectedValue; }
        set
        {
            selectedValue = value;
            UpdatedSelectedItems();
        }
    }

    private void UpdatedSelectedItems()
    {
        if (ListItems == null)
            return;

        ListItems.ForEach(li => li.Selected = Equals(li.Value, SelectedValue));
    }

    private List<RadioButtonListItem> listItems;
    public List<RadioButtonListItem> ListItems
    {
        get { return listItems; }
        set
        {
            listItems = value;
            UpdatedSelectedItems();
        }
    }
}

public class RadioButtonListItem
{
    public bool Selected { get; set; }

    public string Text { get; set; }



    public int Value { get; set; }

    public override string ToString()
    {
        return Value.ToString();
    }
}



public static class HtmlHelperExtensions
{
    /* 
     tagBase: I used tagBase string for building other tag's Id or Name on this. i.e. for tagBase="GenderRadiosForRoomCreate" 
        <td id="GenderRadisoForRoomCreate_Container">
        <input id="GenderRadisoForRoomCreate_Any" name="GenderRadisoForRoomCreate_value" value="1" type="radio"><label for="GenderRadisoForRoomCreate_Any">Any</label>
        <input id="GenderRadisoForRoomCreate_Female" name="GenderRadisoForRoomCreate_value" value="2" type="radio"><label for="GenderRadisoForRoomCreate_Female">Female</label>
        <input id="GenderRadisoForRoomCreate_Male" name="GenderRadisoForRoomCreate_value" value="3" type="radio"><label for="GenderRadisoForRoomCreate_Male">Male</label>
        </td>     
    */
    public static string RadioButtonListFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, RadioButtonListViewModel>> expression, String tagBase) where TModel : class
    {
        return htmlHelper.RadioButtonListFor(expression, tagBase, null);
    }

    public static string RadioButtonListFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, RadioButtonListViewModel>> expression, String tagBase, object htmlAttributes) where TModel : class
    {
        return htmlHelper.RadioButtonListFor(expression, tagBase, new RouteValueDictionary(htmlAttributes));
    }

    public static string RadioButtonListFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, RadioButtonListViewModel>> expression, String tagBase, IDictionary<string, object> htmlAttributes) where TModel : class
    {        
        var inputName = tagBase;
        RadioButtonListViewModel radioButtonList = GetValue(htmlHelper, expression);

        if (radioButtonList == null)
            return String.Empty;

        if (radioButtonList.ListItems == null)
            return String.Empty;


        var containerTag = new TagBuilder("td");
        containerTag.MergeAttribute("id", inputName + "_Container");                
        foreach (var item in radioButtonList.ListItems)
        {
            var radioButtonTag = RadioButton(htmlHelper, inputName, new SelectListItem{Text=item.Text, Selected = item.Selected, Value = item.Value.ToString()}, htmlAttributes);

            containerTag.InnerHtml += radioButtonTag;
        }

        return containerTag.ToString();
    }

    public static string RadioButton(this HtmlHelper htmlHelper, string name, SelectListItem listItem,
                         IDictionary<string, object> htmlAttributes)
    {
        var inputIdSb = new StringBuilder();
        inputIdSb.Append(name);

        var sb = new StringBuilder();

        var builder = new TagBuilder("input");
        if (listItem.Selected) builder.MergeAttribute("checked", "checked");
        builder.MergeAttribute("type", "radio");
        builder.MergeAttribute("value", listItem.Value);
        builder.MergeAttribute("id", inputIdSb.ToString() + "_" + listItem.Text);    
        builder.MergeAttribute("name", name + "_value");
        builder.MergeAttributes(htmlAttributes);
        sb.Append(builder.ToString(TagRenderMode.SelfClosing));
        sb.Append(RadioButtonLabel(inputIdSb.ToString(), listItem.Text, htmlAttributes));
        return sb.ToString();
    }

    public static string RadioButtonLabel(string inputId, string displayText,
                                 IDictionary<string, object> htmlAttributes)
    {
        var labelBuilder = new TagBuilder("label");
        labelBuilder.MergeAttribute("for", inputId + "_" + displayText);
        labelBuilder.MergeAttributes(htmlAttributes);
        labelBuilder.InnerHtml = displayText;

        return labelBuilder.ToString(TagRenderMode.Normal);
    }


    public static TProperty GetValue<TModel, TProperty>(HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression) where TModel : class
    {
        TModel model = htmlHelper.ViewData.Model;
        if (model == null)
        {
            return default(TProperty);
        }
        Func<TModel, TProperty> func = expression.Compile();
        return func(model);
    }
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.