[ASP.net MVC] ViewModel修改資料+DropDownList下拉選單連動
※2013.5.3追記:已寫了一篇更簡潔的解法:[ASP.net MVC4] 使用@Html.DropDownListFor()+Partial View部份檢視實現連動下拉選單(無for-loop方式)
來源討論串:關於MVC連動式下拉選單 修改資料的問題
先建SQL資料:
Create table Member
(
 id int identity primary key,
 memberName varchar(50),
 CountryId int,/*國家id*/
 StateID int /*州id*/
)
Go
Create table Country
(
 CountryId int primary key,
 CountryName varchar(50)
)
Go
Insert into Country values ('1','台灣'),('2','中國')
Create table [State]
(
 StateId int primary key,
 CountryID int,
 StateName varchar(50)
)
Go
Insert into [State] values ('1','1','臺北市'),('2','1','臺北縣'),('3','2','江蘇省'),('4','2','山東省')
Insert into Member values ('Shadow','1','1'),('tester','2','4')
會員的資料
	
國家表的資料
	
省州的資料
	
View
畫面上有兩個下拉選單,一個是CountryId一個是StateID,當CountryId選單改變時,需靠jQuery Ajax動態改變StateID的選項
<script type="text/javascript">
    $(document).ready(init);
    function init() {
        $("select[id='CountryId']").change(function () {/*當國家的下拉選單改變時*/
            var CountryId = $(this).val(); //取出CountryId
            $.post("/Home/generateStateList", { CountryId: CountryId }, callbackHandler);
        });
    }
    function callbackHandler(htmlVal) {
        $("select[id='StateID']").html(htmlVal);/*把省州下拉選單的option改變*/
    }
    
    </script>
HomeController的generateStateList
public ActionResult generateStateList(int CountryID)
        {
            StringBuilder sb = new StringBuilder();
            using (AddressEntities db = new AddressEntities())
            {
                var ss = from sss in db.States
                         where sss.CountryID == CountryID
                         select sss;
                foreach (var item in ss)
                {
                    sb.Append("<option value='"+item.StateId+"'>"+item.StateName+"</option>");
                }
                
            }
            return Content(sb.ToString(), "text/html");
        }
以上的連動式下拉選單完成,已經夠精簡了
接著看修改的程式
Step1. 確認Route定義
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace MvcApplication1
{
    // 注意: 如需啟用 IIS6 或 IIS7 傳統模式的說明,
    // 請造訪 http://go.microsoft.com/?LinkId=9394801
    public class MvcApplication : System.Web.HttpApplication
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.MapRoute(
                "Default", // 路由名稱
                "{controller}/{action}/{id}", // URL 及參數
                new { controller = "Home", action = "MemberList", id = UrlParameter.Optional } // 參數預設值
            );
        }
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            RegisterRoutes(RouteTable.Routes);
        }
    }
}
Step 2.首頁的View(MemberList.aspx)
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<MvcApplication1.Models.Member>>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
	MemberList
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2>MemberList</h2>
    <table>
        <tr>
        <th> </th>
            <th>
                id
            </th>
            <th>
                memberName
            </th>
            <th>
                CountryId
            </th>
            <th>
                StateID
            </th>
        </tr>
    <% foreach (var item in Model) { %>
    
        <tr>
            <td>
                <%: Html.RouteLink("編輯", "Default", new { controller = "Home", action = "MemberEdit", id = item.id })%>
            </td>
            <td>
                <%: item.id %>
            </td>
            <td>
                <%: item.memberName %>
            </td>
            <td>
                <%: item.CountryId %>
            </td>
            <td>
                <%: item.StateID %>
            </td>
        </tr>
    
    <% } %>
    </table>
</asp:Content>
編輯會員資料的View(MemberEdit.aspx)
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MvcApplication1.Models.Member>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    EditMember
        
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<script type="text/javascript">
    $(document).ready(init);
    function init() {
        $("select[id='CountryId']").change(function () {/*當國家的下拉選單改變時*/
            var CountryId = $(this).val(); //取出CountryId
            $.post("/Home/generateStateList", { CountryId: CountryId }, callbackHandler);
        });
    }
    function callbackHandler(htmlVal) {
        $("select[id='StateID']").html(htmlVal);
    }
    
    </script>
    <h2>Member</h2>
    <% using (Html.BeginForm("MemberEdit","Home",FormMethod.Post)) {%>
        <%: Html.ValidationSummary(true) %>
        
        <fieldset>
            <legend>Fields</legend>
           
            <div class="editor-label">
                <%: Html.LabelFor(model => model.id) %>
            </div>
            <div class="editor-field">
                <%: Html.TextBoxFor(model => model.id , new { disabled = "disabled" })%>
                <%: Html.ValidationMessageFor(model => model.id) %>
            </div>
            
            <div class="editor-label">
                <%: Html.LabelFor(model => model.memberName) %>
            </div>
            <div class="editor-field">
                <%: Html.TextBoxFor(model => model.memberName) %>
                <%: Html.ValidationMessageFor(model => model.memberName) %>
            </div>
            
            <div class="editor-label">
                <%: Html.LabelFor(model => model.CountryId) %>
            </div>
            <div class="editor-field">
                <%: Html.DropDownListFor(model => model.CountryId, (List<SelectListItem>)ViewData["countryList"])%>
                <%: Html.ValidationMessageFor(model => model.CountryId) %>
            </div>
            
            <div class="editor-label">
                <%: Html.LabelFor(model => model.StateID) %>
            </div>
            <div class="editor-field">
                <%: Html.DropDownListFor(model =>model.StateID,(List<SelectListItem>)ViewData["stateList"])%>
                <%: Html.ValidationMessageFor(model => model.StateID) %>
            </div>
            
            <p>
                <input type="submit" value="Save" />
            </p>
        </fieldset>
    <% } %>
   
</asp:Content>
Step 3. HomeController
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.ComponentModel.DataAnnotations;
using System.Data.SqlClient;
using System.Text;
using MvcApplication1.Models;
using System.Collections;
namespace MvcApplication1.Controllers
{
    [HandleError]
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return RedirectToAction("MemberList");
        }
        public ActionResult About()
        {
            return View();
        }
        [HttpGet]/*依據Route所傳的id,撈出一筆會員資料*/
        public ActionResult MemberEdit(int id)
        {
            AddressEntities db = new AddressEntities();
            var members = from c in db.Members
                          where c.id == id
                          select c;
            Member member = null;
            foreach (var m in members)
            {
                member = m;
                break;
            }
            List<SelectListItem> countryItems = new List<SelectListItem>();
            var cc = from ccc in db.Countries
                     select ccc;
            /*創建Country下拉選單*/
            foreach (var item in cc)
            {
                SelectListItem sli = new SelectListItem();
                sli.Value = item.CountryId.ToString();
                sli.Text = item.CountryName;
                if (member.CountryId.Value == item.CountryId)
                {
                    sli.Selected = true;/*選在要編輯的會員上*/
                }
                countryItems.Add(sli);
                generateStateList(db, member, member.CountryId.Value);
            }
            ViewData["countryList"] = countryItems;
            return View(member);
        }
        private void generateStateList(AddressEntities db,Member member,int CountryID)
        {
            List<SelectListItem> stateItems = new List<SelectListItem>();
            var ss = from sss in db.States
                     where sss.CountryID==CountryID
                     select sss;
            /*創建State下拉選單*/
            foreach (var item in ss)
            {
                SelectListItem sli = new SelectListItem();
                sli.Value = item.StateId.ToString();
                sli.Text = item.StateName;
                if (member.StateID.Value == item.StateId)
                {
                    sli.Selected = true;/*選在要編輯的會員上*/
                }
                stateItems.Add(sli);
            }
            ViewData["stateList"] = stateItems;
        }
        public ActionResult generateStateList(int CountryID)
        {
            StringBuilder sb = new StringBuilder();
            using (AddressEntities db = new AddressEntities())
            {
                var ss = from sss in db.States
                         where sss.CountryID == CountryID
                         select sss;
                foreach (var item in ss)
                {
                    sb.Append("<option value='"+item.StateId+"'>"+item.StateName+"</option>");
                }
                
            }
            return Content(sb.ToString(), "text/html");
        }
    
        [HttpPost]
        public ActionResult MemberEdit(MvcApplication1.Models.Member member)
        {
            TempData["member"] = member;
            return RedirectToAction("ShowEditResult");
        }
        
        
        public ActionResult ShowEditResult()
        {
            return View((Member)TempData["member"]);
        }
        public ActionResult MemberList()
        {
            AddressEntities db = new AddressEntities();
            return View(db.Members);
        }
    }
}
Step 4.顯示編輯結果的View(ShowEditResult.aspx)
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MvcApplication1.Models.Member>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
	ShowEditResult
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2>ShowEditResult</h2>
    <table>
        <tr>
            <th>
                id
            </th>
            <th>
                memberName
            </th>
            <th>
                CountryId
            </th>
            <th>
                StateID
            </th>
        </tr>
  
    
        <tr>
            <td>
                <%: Model.id %>
            </td>
            <td>
                <%: Model.memberName %>
            </td>
            <td>
                <%: Model.CountryId %>
            </td>
            <td>
                <%: Model.StateID %>
            </td>
        </tr>
    
 
    </table>
  
</asp:Content>
完成結果畫面:
	
點選第二筆來編輯
預設畫面
	
換個台灣
	
改個memberName並換成臺北縣
	
按下Save後
	
以上從頭到尾都是使用ViewModel實現,有興趣的人
請下載程式碼懶人包研究
==================================================================================================
2011.8.17 10:40 P.M 追記
忽然想到,實務上應該沒人把修改結果秀出來
應該是重新導回List清單頁
所以HomeController裡的方法
[HttpPost]
public ActionResult MemberEdit(MvcApplication1.Models.Member member)
再補充+修改一下
[HttpPost]
        public ActionResult MemberEdit(MvcApplication1.Models.Member member)
        {
            /*實現修改會員資料到DB*/
            using (AddressEntities db = new AddressEntities())
            {
                var members = from m in db.Members
                              where m.id == member.id
                              select m;
                foreach (var me in members)
                {
                    me.memberName = member.memberName;
                    me.CountryId = member.CountryId;
                    me.StateID = member.StateID;
                   
                }
                db.SaveChanges();
            }
            
            /*導回List清單頁*/
            return RedirectToAction("MemberList");
        }
修改過後的整包程式碼