Каскадные выпадающие списки MVC3 - PullRequest
1 голос
/ 29 ноября 2011

Относительно новый для MVC и пытается получить каскадный выпадающий список, работающий на время поезда.

Просматривая множество постов, люди говорят, что вам следует держаться подальше от ViewBag / ViewData и вместо этого сосредоточиться на ViewModels, но я просто не могу разобраться с этим, и это меня заводитстена.Любое учебное пособие кажется сложным или слишком простым, и вся идея viewModel еще не дошла до меня.

Итак, вот мой сценарий: у меня есть система администратора, где сотрудники могут добавлять отдельные поездки на поезде.Для каждого времени поезда у меня есть форма ввода, где пользователь может выбрать компанию, и оттуда я хотел бы, чтобы внизу выпадающего списка заполнялся список номеров поездок, которые указывают маршруты.После того, как они выбрали номер, они могут продолжить работу с остальной частью формы, которая довольно велика, включая время в пути, удобства в поезде и т. Д.

Я создал модель вида примерно так:

public class JourneyNumbersViewModel
    {
        private List<SelectListItem> _operators = new List<SelectListItem>();
        private List<SelectListItem> _journeys= new List<SelectListItem>();

        [Required(ErrorMessage = "Please select an operator")]
        public string SelectedOperator { get; set; }
        [Required(ErrorMessage = "Please select a journey")]
        public string SelectedJourney { get; set; }

        public List<SelectListItem> Journeys
        {
            get { return _journeys; }
        }
        public List<SelectListItem> Operators
        {
            get
            {
                foreach(Operator a in Planner.Repository.OperatorRepository.GetOperatorList())
                {
                    _operators.Add(new SelectListItem() { Text = a.OperatorName, Value = a.OperatorID.ToString() });
                }
                return _operators;
            }
        }
    }

В моем контроллере у меня есть это для представления Create:

    public ActionResult Create()
    {
        return View(new JourneyNumbersViewModel());
    }

И это то, где это действительно не работает для меня - если я изменю свою модель наверхув представлении «Создать»: @model Planner.ViewModels.JourneyNumbersViewModel, остальная часть моей формы выдает ошибки, поскольку модель больше не подходит для остальной части формы.Это так, как это должно работать - что если вам нужно сослаться на несколько моделей представлений с одним представлением?

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

1 Ответ

1 голос
/ 07 декабря 2011

Я сделал нечто подобное. Вот часть кода (заранее извиняюсь за то, что он довольно длинный, но я хотел убедиться, что вы можете воссоздать его на своей стороне):

Вид выглядит так:

using Cascading.Models
@model CascadingModel


@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Cascading Forms</h2>
<table>

@using(Html.BeginForm("Index", "Home"))
{
<tr>
    <td>@Html.LabelFor(m=>m.CategoryId)</td>
    <td>@Html.DropDownListFor(m => m.CategoryId, new SelectList(Model.Categories, "Id", "Name"), string.Empty)</td>
</tr>
<tr>
    <td>@Html.LabelFor(m=>m.ProductId)</td>
    <td>@Html.CascadingDropDownListFor(m => m.ProductId, new SelectList(Model.Products, "Id", "Name"), string.Empty, null, "CategoryId", "Home/CategorySelected")</td>
</tr>
<tr>
    <td>&nbsp;</td>
    <td><input type="submit" value="Go"/></td>
</tr>
}
</table>

Модель выглядит следующим образом:

public class CascadingModel
{
    public int CategoryId { get; set; }
    public List<Category> Categories { get; set; }
    public int ProductId { get; set; }
    public List<Product> Products { get; set; }
}

настоящей «умной» частью системы является Html.CascadingDropDownListFor, который выглядит следующим образом:

public static class MvcHtmlExtensions
{
    public static MvcHtmlString CascadingDropDownListFor<TModel, TProperty>(
        this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TProperty>> expression,
        IEnumerable<SelectListItem> selectList,
        string optionLabel,
        IDictionary<string, Object> htmlAttributes,
        string parentControlName,
        string childListUrl
        )
    {
        var memberName = GetMemberInfo(expression).Member.Name;

        MvcHtmlString returnHtml = Html.SelectExtensions.DropDownListFor(htmlHelper, expression, selectList, optionLabel, htmlAttributes);

        var returnString = MvcHtmlString.Create(returnHtml.ToString() + 
                    @"<script type=""text/javascript"">
                        $(document).ready(function () {
                            $(""#<<parentControlName>>"").change(function () { 
                                var postData = { <<parentControlName>>: $(""#<<parentControlName>>"").val() };
                                $.post('<<childListUrl>>', postData, function (data) {
                                    var options = """";
                                    $.each(data, function (index) {
                                        options += ""<option value='"" + data[index].Id + ""'>"" + data[index].Name + ""</option>"";
                                    });
                                    $(""#<<memberName>>"").html(options);
                                })
                                .error(function (jqXHR, textStatus, errorThrown) { alert(jqXHR.responseText); });
                            });
                        });
                     </script>"
                    .Replace("<<parentControlName>>", parentControlName)
                    .Replace("<<childListUrl>>", childListUrl)
                    .Replace("<<memberName>>", memberName));

        return returnString;

    }

    private static MemberExpression GetMemberInfo(Expression method)
    {
        LambdaExpression lambda = method as LambdaExpression;
        if (lambda == null)
            throw new ArgumentNullException("method");

        MemberExpression memberExpr = null;

        if (lambda.Body.NodeType == ExpressionType.Convert)
        {
            memberExpr = ((UnaryExpression)lambda.Body).Operand as MemberExpression;
        }
        else if (lambda.Body.NodeType == ExpressionType.MemberAccess)
        {
            memberExpr = lambda.Body as MemberExpression;
        }

        if (memberExpr == null)
            throw new ArgumentException("method");

        return memberExpr;
    }
}

Логика контроллера для тех, кто ищет:

public ActionResult CategoriesAndProducts()
{
    var viewModel = new CategoriesAndProductsViewModel();
    viewModel.Categories = FetchCategoriesFromDataBase();
    viewModel.Products = FetchProductsFromDataBase();
    viewModel.CategoryId = viewModel.Categories[0].CategoryId;
    viewModel.ProductId = viewModel.Products.Where(p => p.CategoryId).FirstOrDefault().ProductId;
    return View(viewModel);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...