级联下拉列表MVC3 [英] Cascading dropdown lists MVC3

查看:111
本文介绍了级联下拉列表MVC3的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

相对较新的MVC和试图让一个级联下拉列表的列车时刻表的工作。

Relatively new to MVC and trying to get a cascading dropdown list working for train times.

在看很多帖子后,人们说,你应该从ViewBag /的ViewData望而却步,转而关注的ViewModels,但我似乎无法让我的头轮它,它的驾驶我逼疯了。任何教程似乎无论是复杂或太容易了,整个视图模型的想法只是没有跟我没有点击。

After looking at a lot of posts, people say that you should stay away from ViewBag/ViewData and instead focus on ViewModels, but I just can't seem to get my head round it, and it's driving me up the wall. Any tutorial seems to be either to complex or too easy and the whole viewModel idea just hasn't clicked with me yet.

因此​​,这里是我的情况:我有一个管理系统,工作人员可以添加单独的火车旅行。对于每列火车的时候,我有一个输入表单,用户可以选择一个公司,并从那里,我想DropDownList的下方与旅程的数字,这表明路由的列表来填充。一旦他们选择一个号码,就可以进行的形式,这是相当大的,包括旅行时间,上车等设施的其余部分。

So here is my scenario: I have an admin system where staff can add individual train journeys. For each train time, I have an input form where the user can choose a Company, and from there, I'd like the dropdownlist underneath to populate with a list of journey numbers, which indicate routes. Once they have chosen a number, they can carry on with the rest of the form, which is quite large, including time of travel, facilities on the train etc.

我创建了一个视图模型像这样:

I've created a viewmodel like so:

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

在我的控制器,我有这样的创建视图:

In my controller, I have this for the Create view:

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

和这是它是不是真的为我工作 - 如果我在顶部创建视图改变我的模型: @model Planner.ViewModels.JourneyNumbersViewModel ,然后在模型不再是形式的其余部分正确我窗体的其余部分抛出错误。这是它应该工作的方式 - 如果你需要引用多个视图模型与单一视图什么

And this is where it isn't really working for me - if I change my model at the top of the Create view to: @model Planner.ViewModels.JourneyNumbersViewModel, then the rest of my form throws errors as the model is no longer correct for the rest of the form. Is this the way it is supposed to work - what if you need to reference multiple view models with a single view?

我知道这是一个简单的事情,只要点击它,我会想知道如何在地球上我可以用它摆在首位挣扎,但如果有人能指出我要去哪里错了,我会非常感激。

I know this is a simple thing and as soon as it clicks I'll wonder how on earth I could have struggled with it in the first place, but if anyone can point out where I'm going wrong, I'd be very grateful.

推荐答案

我已经做了类似的事情。下面是一些code的(道歉前期这个是相当长的,但我想,以确保在你的身边,你可以重新创建此):

I have done something similar. Here is some of the code (apologies upfront for this being quite long, but I wanted to make sure you could re-create this on your side):

查看看起来是这样的:

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:

the real "clever" part of the system is the Html.CascadingDropDownListFor which looks as follows:

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

控制器逻辑为那些寻找它:

Controller Logic for those looking for it:

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

这篇关于级联下拉列表MVC3的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆