2012年7月16日 星期一

ASP.NET MVC 3 - 基本三層連動式下拉選單應用

昨天(2012-07-14)是 twMVCASP.NET MVC - 新增、查詢、修改、刪除基本功實戰與資料驗證擴充」研討會,在會後有許多的朋友向研討會講者與 twMVC 的其他成員討論有關 ASP.NET MVC 的問題,有個朋友就問了一個如何在 ASP.NET MVC 中實作「連動式下拉選單」的問題,而稍晚在 twMVC Facebook 粉絲團 就分享了 kevin 在部落格中有關下拉選單操作的三篇文章,

image

分別是:

jQuery 對下拉選單 DropDownList 的操作 - 1

jQuery 對下拉選單 DropDownList 的操作 - 2:連動下拉選單

jQuery 練習題:三層式連動下拉選單(無後端整合)

 

接下來的這篇文章將會逐步說明以基本的 ASP.NET MVC 與 jQuery 功能來實作一個三層連動式下拉選單。

2012-07-16 11:30 更新:文末附上範例程式檔案連結。


第一篇「jQuery 對下拉選單 DropDownList 的操作 - 1」主要是說明如何使用 jQuery 操作下拉選單的各種方法。

第二篇「jQuery 對下拉選單 DropDownList 的操作 - 2:連動下拉選單」則是說明在 ASP.NET MVC 中使用 jQuery 來實作連動下拉選單。

第三篇「jQuery 練習題:三層式連動下拉選單(無後端整合)」則是說明在單純的 HTML 與 jQuery 的情況下,操作 JSON 資料來實作一個三層式的連動下拉選單。

 

既然「jQuery 對下拉選單 DropDownList 的操作 - 2:連動下拉選單」已經有說明在 ASP.NET MVC 中使用 jQuery 來實作連動下拉選單,為何又要再寫這一篇文章呢?

如果你是已經具有 ASP.NET MVC 開發經驗的朋友,對於哪一篇的內容接受度應該是可以的,而如果沒有多少 ASP.NET MVC 開發經驗的朋友,恐怕對於那一篇文章的內容就會有所排斥,更何況是還沒有接觸 ASP.NET MVC 開發經驗的朋友,為什麼這樣說呢?

因為「jQuery 對下拉選單 DropDownList 的操作 - 2:連動下拉選單」這一篇文章隨然說了很多種實作連動下拉選單的方法,但是用的方法都有點 geek !

嗯…… 連動下拉選單,真的是一個經典又基本的開發功能,也會有關係到 AJAX 的應用,所以這次就來寫個比較基本且不會太過於複雜的實作。

 

閱讀接下來的範例所需要具備程度:

剛接觸 ASP.NET MVC 且有自己開發練習、操作過或是了解 jQurey 的 selector 與 AJAX 操作。

 

開發使用環境:

    • Visual Studio 2010
    • ASP.NET MVC 3 (Razor)
    • .NET Framework 4.0
    • C#
    • jQuery 1.7.2
    • ADO.NET Entity Framework 4.3.1
    • MS SQL Server 2008 R2 Express (or MS SQL Server 2005 以上的任一版本)
    • Sample DB:Northwind(北風資料庫)
      http://msdn.microsoft.com/zh-tw/library/ms143221.aspx

 


先看看我們最後要做出來的結果,

image

變動第一層「Customers」下拉選單,改變第二層「Orders」下拉選單內容

image

變動第二層「Orders」下拉選單,改變第三層「Products」下拉選單內容

image

選擇第三層「Products」下拉選單的任一個項目後,顯示「顯示產品資訊」的 button

image

按下「顯示產品資訊」的 button 後則顯示該產品的詳細資訊

image

按下「清除」button 後則會清空「產品詳細資訊」內容、「Products」下拉選單、「Orders」下拉選單,然後將「Customers」下拉選單恢復到預設值

image

 

我們來看看要使用哪些的資料內容來做顯示,

image

第一層下拉選單是顯示「Customers」資料

第二層下拉選單是顯示「Orders」資料

第三層下拉選單是顯示「Products」資料,Products 的資料是使用 OrderID 經由 Order_Details 的關聯來顯示

 

Step.1 建立第一層 Customers 下拉選單

Controller Index Action 方法

public ActionResult Index()
{
    ViewBag.Message = "選擇客戶、訂單、產品後顯示產品資訊";
 
    SelectList selectList = new SelectList(this.GetCustomers(), "CustomerID", "ContactName");
    ViewBag.SelectList = selectList;
 
    return View();
}
 
/// <summary>
/// Gets the customers.
/// </summary>
/// <returns></returns>
private IEnumerable<Customers> GetCustomers()
{
    using (NorthwindEntities db = new NorthwindEntities())
    {
        var query = db.Customers.OrderBy(x => x.CustomerID);
        return query.ToList();
    }
}

View Page 的內容

@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
 
<h2>@ViewBag.Message</h2>
<p>
    Customers:@Html.DropDownList("Customers", (SelectList)ViewBag.SelectList, "請選擇客戶", new { id = "Customers" })
</p>

顯示的結果

image

 

Step.2 建立第二層 Orders 下拉選單

第二層下拉選單的資料內容是根據第一個 Customers 下拉選單所選取的值來決定的,前端 View Page 就會需要用到 jQuery 來做 AJAX 的操作,

 

前端 View Page

<h2>@ViewBag.Message</h2>
<p>
    Customers:@Html.DropDownList("Customers", (SelectList)ViewBag.SelectList, "請選擇客戶", new { id = "Customers" })
</p>
<p>
    Orders:<select id="Orders" name="orders"><option>------</option></select>
</p>

 

jQuery 程式內容

<script type="text/javascript" language="javascript">
<!--
    $(document).ready(function () {
        $('#Customers').change(function () { ChangeCustomer(); });
    });
 
    function ChangeCustomer() {
        var selectedValue = $('#Customers option:selected').val();
        if ($.trim(selectedValue).length > 0) {
            GetOrders(selectedValue);
        }
    }
 
    function GetOrders(customerID) {
        $.ajax({
            url: '@Url.Action("Orders", "Display")',
            data: { customerID: customerID },
            type: 'post',
            cache: false,
            async: false,
            dataType: 'json',
            success: function (data) {
                if (data.length > 0) {
                    $('#Orders').empty();
                    $('#Orders').append($('<option></option>').val('').text('請選擇訂單'));
                    $.each(data, function (i, item) {
                        $('#Orders').append($('<option></option>').val(item.Key).text(item.Value));
                    });
                }
            }
        });
    }
 
-->
</script>

簡單說明上面的程式,我們一開始就先綁定好 Customer 下拉選單的 change 事件,當變動第一層選單的選項後就會去執行 GetOrders() 這個 function,而 GetOrders() 這個 function 內就透過 jQuery.Ajax() 向後端取得 Orders 的 JSON 資料,最後再由這份 JSON 資料去增加下拉選單的 option 內容,而後端產生 Orders JSON 資料的程式如下,

 

DisplayController Orders Action 方法

[HttpPost]
public JsonResult Orders(string customerID)
{
    List<KeyValuePair<string, string>> items = new List<KeyValuePair<string, string>>();
 
    if (!string.IsNullOrWhiteSpace(customerID))
    {
        var orders = this.GetOrders(customerID);
        if (orders.Count() > 0)
        {
            foreach (var order in orders)
            {
                items.Add(new KeyValuePair<string, string>(
                    order.OrderID.ToString(),
                    string.Format("{0} ({1:yyyy-MM-dd})", order.OrderID, order.OrderDate)));
            }
        }
    }
    return this.Json(items);
}
 
/// <summary>
/// Gets the orders.
/// </summary>
/// <param name="customerID">The customer ID.</param>
/// <returns></returns>
private IEnumerable<Orders> GetOrders(string customerID)
{
    using (NorthwindEntities db = new NorthwindEntities())
    {
        var query = db.Orders.Where(x => x.CustomerID == customerID).OrderBy(x => x.OrderDate);
        return query.ToList();
    }
}

因為訂單資料並沒有明確的名稱可以顯示,所以下拉選單的選項顯示名稱就用訂單編號加上訂單日期。

 

顯示的結果

image

 

Step.3 建立第三層 Products 下拉選單

第三層下拉選單的作法就如同第二層下拉選單的作法幾乎快要一樣,只有少數幾個地方是不同的,

 

前端 View Page

<p>
    Customers:@Html.DropDownList("Customers", (SelectList)ViewBag.SelectList, "請選擇客戶", new { id = "Customers" })
</p>
<p>
    Orders:<select id="Orders" name="orders"><option>------</option></select>
</p>
<p>
    Products:<select id="Products" name="Products"><option>------</option></select>
</p>
<p>
    <input type="button" id="ButtonReset" value="清除" />
    <input type="button" id="ButtonSubmit" value="顯示產品資訊" />
</p>

 

jQuery 程式內容

jQuery 的程式還需要加上第二層下拉選單 change 事件的綁定,如此變動第二層下拉選單食材可以更換第三層選單內容,

 
    $(document).ready(function () {
        $('#Customers').change(function () { ChangeCustomer(); });
        $('#Orders').change(function () { ChangeOrder(); });
 
    });
 
    //中間省略重複的部份
 
    function ChangeOrder() {
        var selectedValue = $('#Orders option:selected').val();
        if ($.trim(selectedValue).length > 0) {
            GetProducts(selectedValue);
        }
    }
 
    function GetProducts(orderID) {
        $.ajax({
            url: '@Url.Action("Products", "Display")',
            data: { orderID: orderID },
            type: 'post',
            cache: false,
            async: false,
            dataType: 'json',
            success: function (data) {
                if (data.length > 0) {
                    $('#Products').empty();
                    $('#Products').append($('<option></option>').val('').text('請選擇產品'));
                    $.each(data, function (i, item) {
                        $('#Products').append($('<option></option>').val(item.Key).text(item.Value));
                    });
                }
            }
        });
    }

 

DisplayController Products Action 方法

[HttpPost]
public JsonResult Products(string orderID)
{
    List<KeyValuePair<string, string>> items = new List<KeyValuePair<string, string>>();
 
    int id = 0;
 
    if (!string.IsNullOrWhiteSpace(orderID) && int.TryParse(orderID, out id))
    {
        var products = this.GetProducts(id);
        if (products.Count() > 0)
        {
            foreach (var product in products)
            {
                items.Add(new KeyValuePair<string, string>(
                    product.ProductID.ToString(),
                    product.ProductName
                ));
            }
        }
    }
    return this.Json(items);
}
 
/// <summary>
/// Gets the products.
/// </summary>
/// <param name="orderID">The order ID.</param>
/// <returns></returns>
private IEnumerable<Products> GetProducts(int orderID)
{
    using (NorthwindEntities db = new NorthwindEntities())
    {
        var query = db.Order_Details.Where(x => x.OrderID == orderID).Select(x => x.Products);
        return query.ToList();
    }
}

 

顯示的結果

image

 

Step.4 顯示產品詳細資訊與其他的前端事件處理

處理完三個下拉選單的連動變化之後,最後要來處理的是第三個下拉選單的 change 事件以及兩個 button 的 click 事件,先來處理第三個 Products 下拉選單的 change 事件處理,當第三個 Products 下拉選單有選取到產品的 option 就會顯示「顯示產品資料」的 button,而「顯示產品資料」的 button 則是改成進入頁面就會隱藏起來而不顯示,

<script type="text/javascript" language="javascript">
<!--
    $(document).ready(function () {
        $('#Customers').change(function () { ChangeCustomer(); });
        $('#Orders').change(function () { ChangeOrder(); });
        $('#Products').change(function () { ChangeProduct(); });
 
        $('#ButtonSubmit').hide();
    });
 
    //////
    ////// 中間省略
    //////
 
    function ChangeProduct() {
        var selectedValue = $('#Products option:selected').val();
        if ($.trim(selectedValue).length > 0) {
            $('#ButtonSubmit').show();
        }
        else {
            $('#ButtonSubmit').hide();
            $('#ProductInfo').empty();
        }
    }
 
-->
</script>

再來就是處理「顯示產品資訊」button 的 click 事件,當按下這個 button 之後就會把第三個 Products 下拉選單的選取值給送到後端,然後再把產品的詳細資料以 PartialView 傳回到前端,前端頁面再顯示到指定的容器中,這一段的處理是會用到 jQuery Ajax。

 

View Page 內容

 
@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
 
<h2>@ViewBag.Message</h2>
<p>
    Customers:@Html.DropDownList("Customers", (SelectList)ViewBag.SelectList, "請選擇客戶", new { id = "Customers" })
</p>
<p>
    Orders:<select id="Orders" name="orders"><option>------</option></select>
</p>
<p>
    Products:<select id="Products" name="Products"><option>------</option></select>
</p>
<p>
    <input type="button" id="ButtonReset" value="清除" />
    <input type="button" id="ButtonSubmit" value="顯示產品資訊" />
</p>
<hr />
<div id="ProductInfo"></div>

 

jQuery 程式內容

<script type="text/javascript" language="javascript">
<!--
    $(document).ready(function () {
        $('#Customers').change(function () { ChangeCustomer(); });
        $('#Orders').change(function () { ChangeOrder(); });
        $('#Products').change(function () { ChangeProduct(); });
 
        $('#ButtonSubmit').hide().click(function () { DisplayProductInfo(); });
    });
 
    //////
    ////// 中間省略
    //////
 
    function DisplayProductInfo() {
        var selectedValue = $('#Products option:selected').val();
        if ($.trim(selectedValue).length > 0) {
            $.ajax({
                url: '@Url.Action("ProductInfo", "Display")',
                data: { productID: selectedValue },
                type: 'post',
                cache: false,
                async: false,
                dataType: 'html',
                success: function (data) {
                    if (data.length > 0) {
                        $('#ProductInfo').empty();
                        $('#ProductInfo').html(data);
                    }
                }
            });
        }
    }
 
-->
</script>

 

DisplayController ProductInfo Action 方法

[HttpPost]
public ActionResult ProductInfo(string productID)
{
    int id = 0;
 
    if (!string.IsNullOrWhiteSpace(productID) && int.TryParse(productID, out id))
    {
        var product = this.GetProduct(id);
        ViewData.Model = product;
    }
    return PartialView("_ProductInfo");
}
 
/// <summary>
/// Gets the product.
/// </summary>
/// <param name="productID">The product ID.</param>
/// <returns></returns>
private Products GetProduct(int productID)
{
    using (NorthwindEntities db = new NorthwindEntities())
    {
        return db.Products.FirstOrDefault(x => x.ProductID == productID);
    }
}

 

PartialView - 「_ProductInfo.cshtml」

@model Lab_Of_MVC3_DropDownList.Models.Products
 
<fieldset>
    <legend>Product Info</legend>
 
    <div class="display-label">ProductName</div>
    <div class="display-field">@Model.ProductName</div>
 
    <div class="display-label">SupplierID</div>
    <div class="display-field">@Model.SupplierID</div>
 
    <div class="display-label">CategoryID</div>
    <div class="display-field">@Model.CategoryID</div>
 
    <div class="display-label">QuantityPerUnit</div>
    <div class="display-field">@Model.QuantityPerUnit</div>
 
    <div class="display-label">UnitPrice</div>
    <div class="display-field">@String.Format("{0:F}", Model.UnitPrice)</div>
 
    <div class="display-label">UnitsInStock</div>
    <div class="display-field">@Model.UnitsInStock</div>
 
    <div class="display-label">UnitsOnOrder</div>
    <div class="display-field">@Model.UnitsOnOrder</div>
 
    <div class="display-label">ReorderLevel</div>
    <div class="display-field">@Model.ReorderLevel</div>
 
    <div class="display-label">Discontinued</div>
    <div class="display-field">@Model.Discontinued</div>
</fieldset>
 

 

最後還要處理的就是「清除」button 的 click 事件

jQuery 程式內容

<script type="text/javascript" language="javascript">
<!--
    $(document).ready(function () {
        $('#Customers').change(function () { ChangeCustomer(); });
        $('#Orders').change(function () { ChangeOrder(); });
        $('#Products').change(function () { ChangeProduct(); });
 
        $('#ButtonSubmit').hide().click(function () { DisplayProductInfo(); });
        $('#ButtonReset').click(function () { ResetContent(); });
    });
 
    function ResetContent() {
        $('#Customers option:eq(0)').attr('selected', true);
        $('#Orders').empty();
        $('#Products').empty();
        $('#ButtonSubmit').hide();
        $('#ProductInfo').empty();
    }
 
    //////
    ////// 其餘省略
    //////
 
-->
</script>

按下「清除」button 之後要做的事情就是把 ProductInfo 內容清除,第二層與第三層下拉選單也清除,隱藏「顯示產品資料」button,以及要將第一個下拉選單的選取 option 設為最前面的那一個。

 

顯示的結果

還沒有選擇第三個下拉選單的選取值之前,「顯示產品資訊」button 是沒有出現的

image

選了第三個下拉選單的產品選項之後才會出現「顯示產品資訊」button

image

按下「顯示產品資訊」button 則會在下面顯示產品詳細資訊

image

更換第三個下拉選單的產品選項也會更換產品詳細資訊

image

當按下「清除」button 之後就會清除產品詳細資訊內容以及清空下拉選單的值

image

 

Display/Index.cshtml 與 jQuery 程式內容

@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
 
<h2>@ViewBag.Message</h2>
<p>
    Customers:@Html.DropDownList("Customers", (SelectList)ViewBag.SelectList, "請選擇客戶", new { id = "Customers" })
</p>
<p>
    Orders:<select id="Orders" name="orders"><option>------</option></select>
</p>
<p>
    Products:<select id="Products" name="Products"><option>------</option></select>
</p>
<p>
    <input type="button" id="ButtonReset" value="清除" />
    <input type="button" id="ButtonSubmit" value="顯示產品資訊" />
</p>
<hr />
<div id="ProductInfo"></div>
 
 
@if (false){ <script src="../../Scripts/jquery-1.7.2.min.js" type="text/javascript"></script> }
<script type="text/javascript" language="javascript">
<!--
    $(document).ready(function () {
        $('#Customers').change(function () { ChangeCustomer(); });
        $('#Orders').change(function () { ChangeOrder(); });
        $('#Products').change(function () { ChangeProduct(); });
 
        $('#ButtonSubmit').hide().click(function () { DisplayProductInfo(); });
        $('#ButtonReset').click(function () { ResetContent(); });
    });
 
    function ResetContent() {
        $('#Customers option:eq(0)').attr('selected', true);
        $('#Orders').empty();
        $('#Products').empty();
        $('#ButtonSubmit').hide();
        $('#ProductInfo').empty();
    }
 
 
    function ChangeCustomer() {
        var selectedValue = $('#Customers option:selected').val();
        if ($.trim(selectedValue).length > 0) {
            GetOrders(selectedValue);
        }
    }
 
    function GetOrders(customerID) {
        $.ajax({
            url: '@Url.Action("Orders", "Display")',
            data: { customerID: customerID },
            type: 'post',
            cache: false,
            async: false,
            dataType: 'json',
            success: function (data) {
                if (data.length > 0) {
                    $('#Orders').empty();
                    $('#Orders').append($('<option></option>').val('').text('請選擇訂單'));
                    $.each(data, function (i, item) {
                        $('#Orders').append($('<option></option>').val(item.Key).text(item.Value));
                    });
                }
            }
        });
    }
 
    function ChangeOrder() {
        var selectedValue = $('#Orders option:selected').val();
        if ($.trim(selectedValue).length > 0) {
            GetProducts(selectedValue);
        }
    }
 
    function GetProducts(orderID) {
        $.ajax({
            url: '@Url.Action("Products", "Display")',
            data: { orderID: orderID },
            type: 'post',
            cache: false,
            async: false,
            dataType: 'json',
            success: function (data) {
                if (data.length > 0) {
                    $('#Products').empty();
                    $('#Products').append($('<option></option>').val('').text('請選擇產品'));
                    $.each(data, function (i, item) {
                        $('#Products').append($('<option></option>').val(item.Key).text(item.Value));
                    });
                }
            }
        });
    }
 
    function ChangeProduct() {
        var selectedValue = $('#Products option:selected').val();
        if ($.trim(selectedValue).length > 0) {
            $('#ButtonSubmit').show();
        }
        else {
            $('#ButtonSubmit').hide();
            $('#ProductInfo').empty();
        }
    }
 
    function DisplayProductInfo() {
        var selectedValue = $('#Products option:selected').val();
        if ($.trim(selectedValue).length > 0) {
            $.ajax({
                url: '@Url.Action("ProductInfo", "Display")',
                data: { productID: selectedValue },
                type: 'post',
                cache: false,
                async: false,
                dataType: 'html',
                success: function (data) {
                    if (data.length > 0) {
                        $('#ProductInfo').empty();
                        $('#ProductInfo').html(data);
                    }
                }
            });
        }
    }
 
-->
</script>

PartialView「Display/_ProductInfo.cshtml」內容

@model Lab_Of_MVC3_DropDownList.Models.Products
 
<fieldset>
    <legend>Product Info</legend>
 
    <div class="display-label">ProductName</div>
    <div class="display-field">@Model.ProductName</div>
 
    <div class="display-label">SupplierID</div>
    <div class="display-field">@Model.SupplierID</div>
 
    <div class="display-label">CategoryID</div>
    <div class="display-field">@Model.CategoryID</div>
 
    <div class="display-label">QuantityPerUnit</div>
    <div class="display-field">@Model.QuantityPerUnit</div>
 
    <div class="display-label">UnitPrice</div>
    <div class="display-field">@String.Format("{0:F}", Model.UnitPrice)</div>
 
    <div class="display-label">UnitsInStock</div>
    <div class="display-field">@Model.UnitsInStock</div>
 
    <div class="display-label">UnitsOnOrder</div>
    <div class="display-field">@Model.UnitsOnOrder</div>
 
    <div class="display-label">ReorderLevel</div>
    <div class="display-field">@Model.ReorderLevel</div>
 
    <div class="display-label">Discontinued</div>
    <div class="display-field">@Model.Discontinued</div>
</fieldset>
 

DisplayController.cs 內容

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Lab_Of_MVC3_DropDownList.Models;
 
namespace Lab_Of_MVC3_DropDownList.Controllers
{
    public class DisplayController : Controller
    {
        public ActionResult Index()
        {
            ViewBag.Message = "選擇客戶、訂單、產品後顯示產品資訊";
 
            SelectList selectList = new SelectList(this.GetCustomers(), "CustomerID", "ContactName");
            ViewBag.SelectList = selectList;
 
            return View();
        }
 
        /// <summary>
        /// Gets the customers.
        /// </summary>
        /// <returns></returns>
        private IEnumerable<Customers> GetCustomers()
        {
            using (NorthwindEntities db = new NorthwindEntities())
            {
                var query = db.Customers.OrderBy(x => x.CustomerID);
                return query.ToList();
            }
        }
 
 
        [HttpPost]
        public JsonResult Orders(string customerID)
        {
            List<KeyValuePair<string, string>> items = new List<KeyValuePair<string, string>>();
 
            if (!string.IsNullOrWhiteSpace(customerID))
            {
                var orders = this.GetOrders(customerID);
                if (orders.Count() > 0)
                {
                    foreach (var order in orders)
                    {
                        items.Add(new KeyValuePair<string, string>(
                            order.OrderID.ToString(),
                            string.Format("{0} ({1:yyyy-MM-dd})", order.OrderID, order.OrderDate)));
                    }
                }
            }
            return this.Json(items);
        }
 
        /// <summary>
        /// Gets the orders.
        /// </summary>
        /// <param name="customerID">The customer ID.</param>
        /// <returns></returns>
        private IEnumerable<Orders> GetOrders(string customerID)
        {
            using (NorthwindEntities db = new NorthwindEntities())
            {
                var query = db.Orders.Where(x => x.CustomerID == customerID).OrderBy(x => x.OrderDate);
                return query.ToList();
            }
        }
 
 
        [HttpPost]
        public JsonResult Products(string orderID)
        {
            List<KeyValuePair<string, string>> items = new List<KeyValuePair<string, string>>();
 
            int id = 0;
 
            if (!string.IsNullOrWhiteSpace(orderID) && int.TryParse(orderID, out id))
            {
                var products = this.GetProducts(id);
                if (products.Count() > 0)
                {
                    foreach (var product in products)
                    {
                        items.Add(new KeyValuePair<string, string>(
                            product.ProductID.ToString(),
                            product.ProductName
                        ));
                    }
                }
            }
            return this.Json(items);
        }
 
        /// <summary>
        /// Gets the products.
        /// </summary>
        /// <param name="orderID">The order ID.</param>
        /// <returns></returns>
        private IEnumerable<Products> GetProducts(int orderID)
        {
            using (NorthwindEntities db = new NorthwindEntities())
            {
                var query = db.Order_Details.Where(x => x.OrderID == orderID).Select(x => x.Products);
                return query.ToList();
            }
        }
 
 
        [HttpPost]
        public ActionResult ProductInfo(string productID)
        {
            int id = 0;
 
            if (!string.IsNullOrWhiteSpace(productID) && int.TryParse(productID, out id))
            {
                var product = this.GetProduct(id);
                ViewData.Model = product;
            }
            return PartialView("_ProductInfo");
        }
 
        /// <summary>
        /// Gets the product.
        /// </summary>
        /// <param name="productID">The product ID.</param>
        /// <returns></returns>
        private Products GetProduct(int productID)
        {
            using (NorthwindEntities db = new NorthwindEntities())
            {
                return db.Products.FirstOrDefault(x => x.ProductID == productID);
            }
        }
 
    }
}

 

影片操作畫面

 

 

範例程式下載連結:

https://dl.dropbox.com/u/26764200/Lab/Lab_Of_MVC3_DropDownList.7z

Sample DB:Northwind(北風資料庫)http://msdn.microsoft.com/zh-tw/library/ms143221.aspx

 


連動下拉選單是用來練習 ASP.NET MVC 及 jQuery 的 AJAX 應用的好題目,只要你能夠熟練並了解各個步驟的應用與操作,在開發其他 ASP.NET MVC 的基本 AJAX 功能都可以迎刃而解,最後還是一句老話,文章除了拿來看以外,也希望看文章之後也要親自動手做一遍!

 

以上

13 則留言:

  1. 您好:
    最近常常看您的MVC文章,受益良多,想在此請教,如果我的環境是VS2010+MVC4,我要跑您的範例專案是要安裝http://www.microsoft.com/zh-tw/download/details.aspx?id=4211
    嗎?我目前裝不起來,所以想問問您。
    您會更新MVC4的範例版本嗎?

    回覆刪除
    回覆
    1. Hello, 我所提供的範例當初是以 VS2010 + ASP.NET MVC 3 所編寫的,不知道在你的環境下是發生了什麼樣的錯誤,不過我會建議你不用太執著於我所提供的範例程式一定要在你的環境上可以執行,主要還是程式碼本身。

      所以我會建議你可以依據你目前的環境(VS2010 + ASP.NET MVC 4)建立一個新的 ASP.NET MVC 專案來後實作文章裡的各種操作,這篇文章裡的程式碼在 MVC 3 或 MVC 4 都是一樣的,不會有版本上的差異,不一樣的也只有在網站 Template 不同以及 MVC 4 一些設定上多出幾個檔案的不同。

      另外這篇文章的範例檔應當是不會有 MVC 4 的更新版本,理由就是上面所說的,基本的程式操作以及 View 裡的 Razor Syntax 用法與 jQuery 是不會有 MVC 3, MVC 4 的差異。

      PS. 如果真的有問題的話,假如你又剛好在台北,可以考慮週四晚上來參加 twMVC 的聚會,不需要報名、沒有固定形式,就是一群 ASP.NET MVC 開發同好一起討論、研究。
      http://mvc.tw

      刪除
    2. 您好:
      謝謝您的回應,我這邊應該是因為沒有包含MVC3的環境所以範例專案開不起來,VS2010似乎只有預裝MVC2,我重新開MVC4專案一步一步動手做,目前沒什麼問題,再次謝謝您詳細的範例。

      刪除
    3. Hello,
      VS2010 是 2010 年所發佈的,安裝時是有預裝 ASP.NET MVC 2,
      而 ASP.NET MVC 3 是 2011 年發佈,所以在 VS2010 裡是要另外安裝的。

      刪除
  2. 您好凱文,

    你的解釋都非常好,將使而不是使用下拉列表的例子,使用的CheckedListBox。

    回覆刪除
  3. K大您好,非常感謝您的教學,小弟最近都在看您的教學來學習
    小弟照您的教學,做出一個下拉式選單
    有個問題想要請教您
    今天我的資料表中有三筆資料,Value分別是Y、Y、N
    我只想顯示出Value是Y的資料,該如何設定?

    回覆刪除
    回覆
    1. 這應該是在產生給下拉選單資料時就要先篩選好的,而不是資料拿來就直接塞給下拉選單。

      重新整理好你的問題,好好地理解你的需求,再重新發問一次,因為我無法你所說的

      刪除
  4. 您好!感謝分享做法
    但想向您請教,我依循您的作法作到第二層下拉選單時,
    第二層選單顯示出來的text一直是[Object object],
    想詢問您是否也有遇到這樣的情況,謝謝您。

    回覆刪除
    回覆
    1. 這邊有範例程式
      https://github.com/kevintsengtw/MVC-DropDownList-Samples

      部落格頁面最上方有個「範例程式 @ GitHub」
      http://kevintsengtw.blogspot.com/p/github.html
      這邊有整理了部落格大部分文章的範例程式

      刪除
    2. http://kevintsengtw.blogspot.com/2015/06/aspnet-mvc-dropdownlist-github.html

      刪除
  5. 請教一下版主有關DisplayController.cs
    1,相當多gecustomr(),getorder(id),getproduct(id)等取資料部分,請教這部分是否可分開在其他cs上做處理(可提供其他controller使用),由controller接收,後傳輸到前台cshtml
    2.cshtml可否使用整個String產生html語法直接顯示於前台cshtml,如table input等,這方面是否可顯示,還是會有資安問題擋掉這樣的語法輸出,這樣輸出在post時接收是否會有問題,還是需轉出以asp-for這樣的語法才是完整的做法 謝謝

    回覆刪除
    回覆
    1. 問題一:請參考分層架構系列文章
      問題二:除非特殊考量,一般不會直接將 HTML 以純文字的方式輸出,但有些前端處理的內容,是蠻常以輸出部分 HTML 內容的純文字給前端

      刪除
  6. 版主您好,拜讀您這篇教學後,遇到一些進階的問題,如果我把最後查詢的結果透過Ajax 把Partial View 嵌入到View 裡面,那後續如何實現分頁功能?
    我有使用一些Jquery 的Pagination 套件,奈何在這種透過Ajax 把整個PartialView嵌入到View 裡面,會讓Pagination套件根本就不知道這個Partial View 裡面的HTML Tag元素的存在,自然也就無法發揮前端分頁的功用
    不曉得有解法嗎?感謝。

    回覆刪除

提醒

千萬不要使用 Google Talk (Hangouts) 或 Facebook 及時通訊與我聯繫、提問,因為會掉訊息甚至我是過了好幾天之後才發現到你曾經傳給我訊息過,請多多使用「詢問與建議」(在左邊,就在左邊),另外比較深入的問題討論,或是有牽涉到你實作程式碼的內容,不適合在留言板裡留言討論,請務必使用「詢問與建議」功能(可以夾帶檔案),謝謝。