Как использовать переключатель для выбора элемента списка в MVC3 - PullRequest
0 голосов
/ 13 июля 2011

Мне нужно представить моему пользователю список опций пакета, из которых они выбирают один.Я не хочу использовать список переключателей, так как мне нужны довольно сложные шаблоны для каждого элемента списка.Простите, но я просто не могу понять, как связать столбец переключателей со свойством выбора в моей модели представления.

Моя модель представления имеет SelectedPackageId (int) исписок MemberPackageListItem моделей просмотра, представляющих отдельные пакеты.MemberPackageListItem имеет PackageId (int), поэтому мне нужно связать PackageId выбранного элемента с SelectedPackageId модели корневого представления.

Мне сложно отправить код, поскольку наследование и т. д. затеняет многое из того, что вы хотели бы видеть, поэтому я надеюсь, что моя схема довольно распространенного сценария и некоторых общих рекомендаций по использованию переключателей в этом сценарии будет достаточной, чтобы помочь мне продолжить.

Ответы [ 2 ]

2 голосов
/ 13 июля 2011

Я бы предложил использовать HtmlHelper для отображения списка переключателей следующим образом:

    [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
    public static MvcHtmlString RadioButtonListFor<TModel, TList, TSelectedItem>(
        this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TList>> expression,
        Expression<Func<TModel, TSelectedItem>> selectedItem)
    {
        return RadioButtonListFor(htmlHelper, expression, selectedItem, null /* htmlAttributes */);
    }

    [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
    public static MvcHtmlString RadioButtonListFor<TModel, TList, TSelectedItem>(
        this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TList>> expression, 
        Expression<Func<TModel, TSelectedItem>> selectedItem, object htmlAttributes)
    {
        return RadioButtonListFor(htmlHelper, expression, selectedItem, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
    }

    [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
    public static MvcHtmlString RadioButtonListFor<TModel, TList, TSelectedItem>(
        this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TList>> expression, 
        Expression<Func<TModel, TSelectedItem>> selectedItem, IDictionary<string, object> htmlAttributes)
    {
        if (expression == null)
        {
            throw new ArgumentNullException("expression");
        }

        ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
        IEnumerable<SelectListItem> items = null;
        if (metadata.Model != null)
        {
            IEnumerable<SelectListItem> modelItems = (IEnumerable<SelectListItem>)metadata.Model;
            if (modelItems != null)
            {
                items = modelItems;
            }
        }

        ModelMetadata selectedItemMetadata = ModelMetadata.FromLambdaExpression(selectedItem, htmlHelper.ViewData);

        return RadioButtonListHelper(htmlHelper, metadata, selectedItemMetadata, ExpressionHelper.GetExpressionText(selectedItem), items, htmlAttributes);
    }

    private static MvcHtmlString RadioButtonListHelper(HtmlHelper htmlHelper, ModelMetadata metadata, 
        ModelMetadata selectedItemMetadata, string name, IEnumerable<SelectListItem> selectList, IDictionary<string, object> htmlAttributes)
    {
        // Verify arguments
        if (String.IsNullOrEmpty(name)) throw new ArgumentNullException("name", "Name cannot be null");
        if (selectList == null) throw new ArgumentNullException("selectList", "Select list cannot be null");
        if (selectList.Count() < 1) throw new ArgumentException("Select list must contain at least one value", "selectList");

        string fullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
        string fullId = htmlHelper.ViewData.TemplateInfo.HtmlFieldPrefix + "_" + name;

        IDictionary<string, object> validationAttributes = htmlHelper
            .GetUnobtrusiveValidationAttributes(ExpressionHelper.GetExpressionText(name), selectedItemMetadata);

        // Define items
        StringBuilder items = new StringBuilder();

        // Loop through items
        Int32 index = 0;
        foreach (SelectListItem i in selectList)
        {

            // Define check box input
            TagBuilder input = new TagBuilder("input");
            input.MergeAttribute("type", "radio");
            input.MergeAttribute("name", fullName, true);
            if (i.Selected)
                input.MergeAttribute("checked", "checked");
            input.MergeAttribute("value", i.Value);
            if (index == 0)
                input.MergeAttributes(validationAttributes);
            input.MergeAttributes(htmlAttributes);

            // Define label
            TagBuilder label = new TagBuilder("label");
            label.MergeAttribute("for", fullId + "[" + index.ToString() + "].Selected");
            label.InnerHtml = i.Text;

            // Add item
            items.AppendFormat("\r\t<div>\r\t\t{0}\r\t\t{1}\r\t</div>",
                input.ToString(TagRenderMode.Normal),
                label.ToString(TagRenderMode.Normal));

            index++;
        }
        // Return list
        return new MvcHtmlString(items.ToString() + "\r");
    }

Обратите внимание, что MemberPackageListItem должен иметь тип IEnumerable<SelectListItem>.Использование следующим образом (синтаксис Razor):

    @Html.RadioButtonListFor(m => m.MemberPackageListItem, m => m.SelectedPackageId)

counsellorben

1 голос
/ 13 июля 2011

Хотя я ценю техническую полноту ответа @ counsellorben и буду держать его для дальнейшего использования, сегодня я пришел к более оперативному и не совсем неуклюжему решению jQuery.Селекторы могут быть более конкретными, но мне это сейчас не нужно.Мое решение ниже.Типы радиосигналов сгруппированы по их атрибуту имени, которому присваивается отдельный индекс для каждой строки.Поэтому:

$(function () {
    // Back up current names of package radio buttons, then make all their names the same for grouping.
    $("#packageForm :radio[name$='.IsSelected']").each(function () {
        $(this).attr("oldname", $(this).attr("name"));
    });
    $(":radio[name$='.IsSelected']").attr("name", "Package.IsSelected");

    // Hook the 'submit' click to restore original radio button names.
    $("#packageForm :submit").click(function () {
        $(":radio[name='Package.IsSelected']").each(function () {
            $(this).attr("oldname", $(this).attr("name"));
        });
    });
});  

IsSelected - это мое свойство для каждой строки, которое сообщает мне, если эта строка выбрана, это не свойство jQuery или DOM.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...