Question

relativement nouveau pour MVC et essayer d'obtenir une liste déroulante en cascade travaillant pour les horaires des trains.

Après avoir regardé beaucoup de messages, les gens disent que vous devriez rester loin de ViewBag / ViewData et plutôt se concentrer sur ViewModels, mais je ne peux pas sembler obtenir ma tête ronde, et il me conduit dans le mur. Tout tutoriel semble être soit complexe ou trop facile et toute idée de viewmodel n'a pas cliqué avec moi pour l'instant.

Voici donc mon scénario: j'ai un système d'administration où le personnel peut ajouter les trajets en train individuels. Pour chaque train, j'ai une forme d'entrée où l'utilisateur peut choisir une compagnie, et à partir de là, je voudrais que le sous dropdownlist à remplir avec une liste de numéros voyage, qui indiquent les routes. Une fois qu'ils ont choisi un certain nombre, ils peuvent continuer avec le reste de la forme, ce qui est assez grande, y compris le temps de Voyage, les installations sur le train, etc.

J'ai créé un viewmodel comme ceci:

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;
            }
        }
    }

Dans mon contrôleur, j'ai ce pour la vue Créer:

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

Et c'est là, il ne fonctionne pas vraiment pour moi - si je change mon modèle en haut de la page Créer vue: @model Planner.ViewModels.JourneyNumbersViewModel, puis le reste de ma forme renvoie des erreurs que le modèle n'est plus correct pour le reste de la forme. Est-ce la façon dont il est censé fonctionner - si vous avez besoin de faire référence à plusieurs modèles de vue avec une vue unique

Je sais que c'est une chose simple et dès qu'il clique je me demande comment diable je aurais pu lutté avec en premier lieu, mais si quelqu'un peut indiquer où je vais mal, je très reconnaissant.

Était-ce utile?

La solution

J'ai fait quelque chose de similaire. Voici le code (excuses d'avance pour ce qui est assez long, mais je voulais vous assurer que vous pouvez recréer cela sur votre côté):

Voir ressemble à ceci:

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>

les regards du modèle comme suit:

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; }
}

la partie réelle du système « intelligent » est le Html.CascadingDropDownListFor qui se présente comme suit:

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;
    }
}

Contrôleur logique pour ceux qui recherchent le:

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);
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top