Domanda

Relativamente nuovo per MVC e cercando di ottenere un elenco a cascata discesa a lavorare per gli orari dei treni.

Dopo aver guardato un sacco di posti, la gente dice che si dovrebbe stare lontano da ViewBag / Viewdata e invece concentrarsi sulla ViewModels, ma io proprio non riesco a ottenere la mia testa intorno ad esso, e mi sta guidando fino al muro. Ogni esercitazione sembra essere sia a complessi o troppo facile e l'intera idea ViewModel solo non ha fatto clic con me ancora.

Quindi, ecco il mio scenario: ho un sistema di amministrazione in cui il personale può aggiungere singoli viaggi in treno. Per ogni volta in treno, ho un modulo di input in cui l'utente può scegliere una società, e da lì, mi piacerebbe il sottostante dropdownlist Per compilare un elenco di numeri di percorrenza, che indicano percorsi. Una volta che hanno scelto un certo numero, possono continuare con il resto della forma, che è abbastanza grande, compreso il tempo di viaggio, strutture sul treno, ecc.

Ho creato un ViewModel in questo modo:

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

Nel mio controller, ho questo per la vista Crea:

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

E questo è dove non è davvero lavorando per me - se cambio il mio modello al top della vista Crea per: @model Planner.ViewModels.JourneyNumbersViewModel, poi il resto della mia forma genera errori come il modello non è più corretta per il resto della forma. E 'questo il modo in cui si suppone che il lavoro - che cosa se avete bisogno di fare riferimento a più modelli vista con un unico punto di vista

So che questa è una cosa semplice e non appena scatta mi chiedo come diavolo avrei potuto lottato con esso, in primo luogo, ma se qualcuno può indicare sbagliato dove sto andando, mi piacerebbe molto grato.

È stato utile?

Soluzione

Ho fatto qualcosa di simile. Ecco parte del codice (scuse upfront per questo essere piuttosto lungo, ma ho voluto assicurarsi che si potrebbe ricreare questo dalla vostra parte):

Visualizza assomiglia a questo:

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>

gli sguardi modello come segue:

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 vera parte "intelligente" del sistema è il Html.CascadingDropDownListFor, che appare come segue:

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

Logic Controller per coloro che cercano per esso:

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);
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top