[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");
}
修改過後的整包程式碼