لیست بازشو وابسته به هم در MVC

3/12/2017 MVC
2302

نیاز داریم تا با انتخاب استان نام شهرستانهای متناظر با آن نیز مشاهده شوند

در بسیاری از صفحات نیاز داریم تا با تغییر یکی از ایتمهای لیست باز شو لیست باز شو مرتبط با آن (مثلا ارتباط بین لیست باط شو استان و در مقابل لیست باز شو شهرستانهای متناظر) به روز شود. از طریق jquery و یا ajax میتوان با تغییر ایتمهای لیست اول اطلاعات مربوطه را از بانک اطلاعاتی دریافت کرد. و در لیست باز شو دوم ریخت.

 

 

برای این کار د رModel داریم 

public class City
    {
        public int Id { get; set; }
        [Display(Name = "نام شهر")]
        public string Name { get; set; }
        public int ProvinceId { get; set; }
        public virtual Province Province { get; set; }
        public virtual ICollection<Customer> Customers { get; set; }

    }
  public class Province
    {
        public int Id { get; set; }
        [Display(Name = "نام استان")]
        public string Name { get; set; }
        public virtual ICollection<Customer> Customers { get; set; }
        public virtual ICollection<City> Citis { get; set; }
    }

و در ثبت نام مشتری 

public class Customer
    {
        public int Id { get; set; }
        [Display(Name = "نام")]
        public string FirstName { get; set; }
        [Display(Name = "نام خانوادگی")]
        public string LastName { get; set; }
        [Display(Name = "شماره تلفن")]
        public string Phone { get; set; }
        [Display(Name = "شماره همراه")]
        public string Mobile { get; set; }
        [Display(Name="پست الکترونیک")]
        [DataType(DataType.EmailAddress)]
        public string Email { get; set; }
        [Display(Name = "کد ملی")]
        public string NationalCode { get; set; }
        public int ProvinceId { get; set; }
        public virtual Province  Province { get; set; }
        public int CityId { get; set; }
        public virtual City City { get; set; }
        [Display(Name = "آدرس")]
        public string Address { get; set; }
        public DateTime CreateDate { get; set; }
    }

در ویوو خواهیم داشت 

 <div class="form-group col-md-6 col-sm-12">
            @Html.LabelFor(model => model.ProvinceId, "استان", htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.DropDownListFor(model=>model.ProvinceId, (SelectList)ViewBag.ProvinceId, "انتخاب استان", htmlAttributes: new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.ProvinceId, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group col-md-6 col-sm-12">
            @Html.LabelFor(model => model.CityId, "شهر", htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.DropDownList("CityId",(SelectList)ViewBag.CityId, "انتخاب شهر",  new {@class = "form-control" })
                @Html.ValidationMessageFor(model => model.CityId, "", new { @class = "text-danger" })
            </div>
        </div>

از هر دو حالت DropDownListFor و DropDownList  میتوانید استفاده کنید همانطور که در آستان و شهر متفاوت استفاده شده  است 

در کد های java script  خواهیم داشت 

        $(document).on("change", "#ProvinceId", function (e) {
            var PID = this.value;
            
            $.ajax({
                type: 'GET',
                url: '/customers/ReturnCity',
                dataType:"json",
                data: { ProvinceID: PID },
                
                success: function (ci) {
                    $('#CityId').empty();
                    $.each(ci, function (index, item)
                    {
                        $('#CityId').append($('<option></option>').text(item.Name).val(item.Id));

                    });


                },
            });
        })

 

و در کنترل 

public JsonResult ReturnCity(int ProvinceID)
        {
            db.Configuration.ProxyCreationEnabled = false;
            var ci = db.Citis.Where(x => x.ProvinceId == ProvinceID);
            return Json(ci.ToList(), JsonRequestBehavior.AllowGet);
        }
  public ActionResult Create()
        {
		int i = 0;
            ViewBag.CityId = new SelectList(db.Citis, "Id", "Name");
            ViewBag.CustomerTypeId = new SelectList(db.CustomerTypes, "Id", "Name");
            ViewBag.ProvinceId = new SelectList(db.Provinces, "Id", "Name");
            return PartialView("_Create");
        }

        // POST: Customers/Create
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Create([Bind(Include = "Id,FirstName,LastName,Phone,Mobile,Email,NationalCode,CompanyName,ProvinceId,CityId,Address,CustomerTypeId")] Customer customer)
        {
            if (ModelState.IsValid)
            {
                db.Customers.Add(customer);
                await db.SaveChangesAsync();
                return RedirectToAction("Index");
            }

            ViewBag.CityId = new SelectList(db.Citis, "Id", "Name", customer.CityId);
            ViewBag.CustomerTypeId = new SelectList(db.CustomerTypes, "Id", "Name", customer.CustomerTypeId);
            ViewBag.ProvinceId = new SelectList(db.Provinces, "Id", "Name", customer.ProvinceId);
            return RedirectToAction("Index");
        }

actionResult  اول برای استفاده ajax  است که میبینید هم نام با قسمت url اجکس نام گذاری شده است 

و دو اکشن Create  که نیاز به توضیح خاصی ندارد فقط در اکشن create  دوم با توجه به اینکه ما برای ایجاد مشتری از Modal  استفاده میکردم Redirect  به اکشن Index  زده شده است

البته در اکشن اول (returnCity) با توجه به اینکه json  بر میگردانیم اگر خط کد 

db.Configuration.ProxyCreationEnabled = false;

را ایجاد نکنیم خطا یی مبنی بر 

A circular reference was detected while serializing an object of type 'System.Data.Entity.DynamicProxies.City_14F512F84B33053E91AF620D1BA9085FB7B5113A0

 دریافت خواهیم کرد.

البته در Edit  که برای تغییر جزئیات کاربر یا مشتری استفاده میکنید باید کدهای مربوط به لیست بازشو را تغییر دهید

  <div class="form-group col-md-6 col-sm-12">
            @Html.LabelFor(model => model.ProvinceId, "استان", htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.DropDownList("ProvinceId", null, htmlAttributes: new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.ProvinceId, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group col-md-6 col-sm-12">
            @Html.LabelFor(model => model.CityId, "شهر", htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.DropDownList("CityId", null, htmlAttributes: new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.CityId, "", new { @class = "text-danger" })
            </div>
        </div>

چرا که اگر کدها با Create  یکسان باشد در هر بار نمایش صفحه Edit  لیست استانها و شهر ها را مانند زمان Create  از ابتدا نمایش میدهد.

لطفا در کد های خود در java  حتما به بزرگ و کوچک بودن حروف دقت کنید.

آپدیت : زمانی که روی تغییر کلیک میکنیم لیست تمامی شهرستانها نمایش داده میشود ، برای تغییر در آن باید در کنترل چنین تغییری بدیم

            ViewBag.CityId = new SelectList(db.Citis.Where(x=>x.ProvinceId == customer.ProvinceId), "Id", "Name", customer.CityId);

قسمت where  اضافه شد.