[ASP.net MVC] ViewModel修改資料+DropDownList下拉選單連動

[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')

會員的資料

image

國家表的資料

image

省州的資料

image

 

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>&nbsp;</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>

 

完成結果畫面:

image

點選第二筆來編輯

 

預設畫面

image

 

換個台灣

image

改個memberName並換成臺北縣

image

按下Save後

image

 

以上從頭到尾都是使用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");
        }

修改過後的整包程式碼