iT邦幫忙

0

c# asp.mvc 透過foreach在表格中重複放選單取值的問題

@model IEnumerable<WebMvc2.Models.StViewModel>

        <tr>
            <th>skill id
            <th>org id
            <th>tag name
            <th>skill name
            <th>評分項目
        
        @foreach(var item in this.Model)
        {
            <tr>
                <td>@item.skill_id
                <td>@item.org_id
                <td>@item.tag_name
                <td>@item.skill_name
                <td>
                    <select name="Scores" id="scores">
                        <option value="1">1</option>
                        <option value="2">2</option>
                        <option value="3">3</option>
                        <option value="4">4</option>
                        <option value="5">5</option>
                        <option value="6">6</option>
                        <option value="7">7</option>
                        <option value="8">8</option>
                        <option value="9">9</option>
                        <option value="10">10</option>
                   
                </td>
            
        }
   

如上述程式碼,問題1:我可能會有很多個項目每個項目都會附有一個下拉選單供使用者填寫那我要如何取值以方便日後插入、更新資料庫,因為使用這樣的方式的話每個項目的select選單的id都會一樣是scores。不過我是有想到直接把select 的id屬性用@iem.skill_id取代來抓應該就可了但最近剛學asp.mvc不知道這樣是不是好的方法。

問題2:因為剛從webform轉過來mvc有個疑問因為會針對不同的httpmethod,寫不同的contoller跟view。因為這個表單事件可能發生第一次使用會用插入的,其餘的採用更新的方式。這樣的話我是不是也針對insert跟update分別寫不同的controller跟view以前webform是用if else的方式決定要用哪一種sqlstring但現在改學LinQ不曉得能不能也這樣寫。

看更多先前的討論...收起先前的討論...
問題一:你是想問,有沒有比較好的方式取代?我看不董= =
問題二:應該是寫不同的ACTION 透過HTTPMTHOD判斷使用哪個ACTION
問題一,我目前假如select id放scores的話用JQuery取val的話只能取第一筆應該是因為id重複的關係。但放@item.skill_id的話,jquery不知道該如何取值因為每個的id都不同沒辦法指定。因為目前都是用ajax的方式將資料傳給後端,還是說更新及插入有更好的方法可以用,之前用webform時因為前後端都相依都是透過控制項直接傳到db現在的話就不曉得該用何種方法好
你觸發的地方沒寫出來,插入或更新的按鈕是在迴圈外? 只有一顆?
我還沒寫出來,只有之前webform寫的版本打算先取到值再寫出來。但目前mvc卡在選單的值不知道如何取。
這是之前webform的寫法如下呼叫sql連線跟其方法
sk_count = (Int32)command.ExecuteScalar();
if (sk_count > 0)
{
UpdateEmp(i);
}
else
{
InsertEmp(i);
}
這個要看你實務上,是需要一筆一筆更新,還是整批更新
單筆的樓下好像貼出來了
整批的話看我的回答
整批更新透過迴圈外的按鈕來執行。一筆一筆的話我大致上知道該怎麼做但整批的話還想不到
我有貼了,你在看一下
0
Samuel
iT邦新手 3 級 ‧ 2021-10-28 15:23:18

ViewModel 裡面cs 屬性再擴充一個子class(另一個Sub ViewModel)
然後是一個select (或之前webform的dropdowlist)裡面設置select tag屬性
就能夠達成兩個以上的ViewModel綁定了(一個for table record,一個for select)
白話一點就是一個大的ViewModel Class裡面再包另一個子ViewModel Class

0

問題一:

我還是不知道你按鈕放在哪
1.迴圈內(多按鈕),更新單筆
2.迴圈外(一顆按鈕),批次更新

假設你按鈕是放置在迴圈中,也就是每一筆有一顆更新按鈕,這個好辦,用jqeury

HTML

 @foreach(var item in this.Model)
        {
            <tr>
                <td>@item.skill_id
                <td>@item.org_id
                <td>@item.tag_name
                <td>@item.skill_name
                <td>
                    <select name="Scores" id="scores">
                        <option value="1">1</option>
                        <option value="2">2</option>
                        <option value="3">3</option>
                        <option value="4">4</option>
                        <option value="5">5</option>
                        <option value="6">6</option>
                        <option value="7">7</option>
                        <option value="8">8</option>
                        <option value="9">9</option>
                        <option value="10">10</option>
                   
                </td>
                <td>
                <button class="submitbtn">更新 </button>
                </td>
            </tr>            
        }

JQuery

$('.submitbtn').on("click",function(){

var select = $(this).closet("select");  //由按鈕往上找select
var selectvalue = select.val(); //取值
//dosomething
});

問題二:

沒有一定,分別寫會比較容易讀
硬要寫在同一個Action的話,可以用參數方法傳回Controller做判定

ex:
前端多加一個參數 operate ,類似下面,方法有很多可以自己想別的

<input type="hidden" name="operate" value="insert">
<input type="hidden" name="operate" value="update">

後端Action中,多取參數operate出來,再由此值判定是新增還是更新。

看更多先前的回應...收起先前的回應...

喔喔原來是這個問題啊抱歉沒領會到,我的話因為一開始會有2個下拉選單先選部門再選該部門選員工然後透過[顯示表單資訊]按鈕撈出這個發問裡的上述表單(我是用PartialView的方式寫所以會放在另一個cshtml),之後填完分數會再按一個[儲存]按鈕一次做更新或插入資料庫的動作。所以按鈕是放在迴圈外面

也就是,他查出一堆資訊後,每一列各要選擇一個分數,假設有五個項目,選完後,迴圈外一個儲存,要存完所有分數....

你的項目是固定的嗎,固定的話有個簡單方法可以做,就是用Razor,不過這似乎和你想取ID直接抓類似

假設有5項,且排序固定1 2 3 4 5

@{ int seq = 1;}
@foreach(var item in this.Model)
        {
            <tr>
                <td>@item.skill_id
                <td>@item.org_id
                <td>@item.tag_name
                <td>@item.skill_name
                <td>
                <select name="Scores" id="scores@(seq)">
                        <option value="1">1</option>
                        <option value="2">2</option>
                        <option value="3">3</option>
                        <option value="4">4</option>
                        <option value="5">5</option>
                        <option value="6">6</option>
                        <option value="7">7</option>
                        <option value="8">8</option>
                        <option value="9">9</option>
                        <option value="10">10</option>
                   
                </td>              
            </tr>    
            seq++;
        }

這樣可以分別不同的ID取值

因為項目不固定所以才不知道該怎麼做@@,我是根據部門決定要撈出那些技能每個部門的技能也不同,之前webform我是用findcontrol跑for迴圈抓skill_id的length一個一個抓

坐等大神 /images/emoticon/emoticon01.gif

0
asd3733653
iT邦新手 4 級 ‧ 2021-10-28 17:08:55

首先,你的Model裡面資料的清單,每筆資料都要多一個屬性

//你其他的屬性skill_id、org_id...
public int Scores { get; set; };
public List<SelectListItem> Scores_List { get; set; } = new List<SelectListItem>();

然後你的Controller進來的時候

Scores_List = new List<SelectListItem>()
{
     new SelectListItem { Value = "0", Text = "0", Selected = true },
     new SelectListItem { Value = "1", Text = "1", Selected = false }
     //...以此類推
};

前端:

<select asp-for="@item.Scores" asp-items="@item.Scores_List">
</select>

這樣你在SUBMIT的時候 後端Controller接到Model的時候就會有資料,就可以整批更新了

看更多先前的回應...收起先前的回應...

不懂得可以再問我

Homura iT邦高手 1 級 ‧ 2021-10-28 17:20:06 檢舉

asp-for???
他有說他是寫razor page麻?

???

razor page 跟我的 asp-for 有什麼關係嗎

Homura iT邦高手 1 級 ‧ 2021-10-28 17:31:54 檢舉

不是razor page 用的tag helper嗎?

tag helper 在.net core 都可以用,不管是不是razor page
如果是.net mvc 要用HTML helper

Homura iT邦高手 1 級 ‧ 2021-10-28 17:42:06 檢舉

是啊
但是他好像沒提他是core

對阿我不是用.net core,我是用asp.net web的mvc去寫但我等等再研究看看asd大的寫法

先提供我的程式碼裡面的var form會呼叫GetForm方法:

 StViewModel ss = new StViewModel();
  [HttpPost]
        public ActionResult FormInfo(string emp_no,string org_id)
        {
            //int id = 0;
            ss.Scores_List = new List<SelectListItem>()
            {
                new SelectListItem{Value="0",Text="0",Selected=true},
                new SelectListItem{Value="1",Text="1",Selected=false},
                new SelectListItem{Value="2",Text="2",Selected=false},
            };   
            if (!string.IsNullOrWhiteSpace(emp_no)&& (!string.IsNullOrWhiteSpace(org_id)))
            {
                var form = this.GetForm(emp_no,org_id);
                ViewData.Model = form;
            }
            return PartialView("_FormInfo");
        }
    以下為GetForm方法()
    private List<StViewModel> GetForm(string emp_no,string org_id)
        {
         
            List<StViewModel> query = new List<StViewModel>();
            using (Model2 db = new Model2())
            {
                query = (from s in db.Hao_skill
                         from e in db.emp_data_all 
                         from st in db.Hao_skilltag
                         from t in db.Hao_tag
                         where s.skill_id==st.skill_id && t.tag_id==st.tag_id && st.org_id==org_id && e.emp_no==emp_no
                         select new StViewModel
                         {
                             skill_id=s.skill_id,
                             org_id = e.org_id,
                             tag_name =t.tag_name,
                             skill_name=s.skill_name
                         }
                        ).ToList();
          
                return query;
            
            }
        }

asd大你好我現在用到第二步controller這裡我有個疑問你的Scores_List=new ListSelectListItem這段應該是從model抓過來的,但我現在還沒學到要怎麼從model抓,我現在是再controller裡面先宣告 StViewModel ss = new StViewModel();再拿來用還不知道會不會成功。
因為這樣就不是不是SelectListItem。因為我這樣寫感覺就是要用viewbag另外來放?所以想要請教你

GetForm的方法呢 我看一下

StViewModel
這個Model裡面多以上兩個屬性
public int Scores { get; set; };
public List Scores_List { get; set; } = new List();

然後你select new StViewModel
{
skill_id=s.skill_id,
org_id = e.org_id,
tag_name =t.tag_name,
skill_name=s.skill_name
}
這裡中間把LIST丟進去
會嗎?

select new StViewModel
{
skill_id=s.skill_id,
org_id = e.org_id,
tag_name =t.tag_name,
skill_name=s.skill_name,
Scores_List  = Scores_List 
}

順便貼給你Html Heleper
@Html.DropDownList(@item.Scores, (IEnumerable)@item.Scores_List)
印象中是這樣用

原來可以把list放在裡面這樣啊我以為query這段就是當成sql語法再寫看來我邏輯上的認知還沒切換。我等等來試試看

好像要改用@Html.DropDownListfor但裡面目前有錯誤@@,我參考網路上大家的寫法大多是@Html.DropDownListFor(m=>m.Name, Model.MyList , new { @class = "form-control" }),但我不知道我第一個要放甚麼也不能放會顯示錯誤目前我是放這樣,它是說我的stViewModel沒有DropDownListfor的定義 @Html.DropDownListfor(不知道放甚麼但應該是要放我的選項?但我都放再Scores_List,item.Scores, item.Scores_List);

GetForm方法目前改成這樣

 private List<StViewModel> GetForm(string emp_no,string org_id)
     {
         
   List<StViewModel> query = new List<StViewModel>();
      using (Model2 db = new Model2())
        {
         ss.Scores_List = new List<SelectListItem>()
          {
            new SelectListItem{Value="0",Text="0",Selected=true},
                new SelectListItem{Value="1",Text="1",Selected=false},
                new SelectListItem{Value="2",Text="2",Selected=false},
            };
          query = (from s in db.Hao_skill
                   from e in db.emp_data_all
                   from st in db.Hao_skilltag
                   from t in db.Hao_tag
                   where s.skill_id == st.skill_id && t.tag_id == st.tag_id && st.org_id == org_id && e.emp_no == emp_no
             select new StViewModel
                    {
                         skill_id = s.skill_id,
                         org_id = e.org_id,
                         tag_name = t.tag_name,
                        skill_name = s.skill_name,
                        Scores_List = ss.Scores_List
                      }).ToList();
                return query;
            }
        }

但我認為是因為我再foreach裡面又放dropdownlistfor所以它程式可能抓不到item=>item.scores跟item.Scores_List

@Html.DropDownList(x => @item.Scores, (IEnumerable)@item.Scores_List)

asd大你好我用你的那個方法的話 (IEnumerable)這裡會出現使用泛型類型 'IEnumerable'T需要一個引數的錯誤提示,才改用DropDownListfor但目前2個方式都失敗

附上我的viewmodel,另外一個疑問我目前的Scores我看程式沒有指定值那這樣會顯示東西嗎?

    public class StViewModel
    {
        public string org_id { get; set; }
        public string org_cname { get; set; }
        public string emp_no { get; set; }
        public string emp_name { get; set; }
        public int skill_id { get; set; }
        public string skill_name { get; set; }
        public string tag_name { get; set; }
        public int Scores { get; set; }
        public List<SelectListItem> Scores_List { get; set; } = new List<SelectListItem>();
   
    }

@Html.DropDownList(x => @item.Scores, @item.Scores_List)

選到了就會有值喔

好像要改成這個 @Html.DropDownList(@item.Scores, @item.Scores_List);才不會有錯誤提示。**用x=>會出現無法將lambda類型轉成string因為非委派類型。**但現在去執行會失敗會出現System.NotSupportedException: '無法建立'System.Web.Mvc.SelectListItem' 型別的常數值的錯誤。這個內容僅支援基本型別或列舉型別。'的錯誤再我getform方法的變數query這裡,我的 Scores_List = ss.Scores_List是不是不能放在select new StViewModel{}裡

@Html.DropDownList(@item.Scores, (IEnumerable)@item.Scores_List);

@Html.DropDownList(@item.Scores, (IEnumerable<SelectListItem>)@item.Scores_List);
 query = (from s in db.Hao_skill
                         from e in db.emp_data_all
                         from st in db.Hao_skilltag
                         from t in db.Hao_tag
                         where s.skill_id == st.skill_id && t.tag_id == st.tag_id && st.org_id == org_id && e.emp_no == emp_no
                         select new StViewModel
                         {
                             skill_id = s.skill_id,
                             org_id = e.org_id,
                             tag_name = t.tag_name,
                             skill_name = s.skill_name,
                             Scores_List=ss.Scores_List
                         }
                        ).ToList();

asd大你好現在的問題主要是我query這裡會有無法建立'System.Web.Mvc.SelectListItem' 型別的常數值的錯誤。這個內容僅支援基本型別或列舉型別的錯誤發生。有在想是不是我ss.Scores_List是我另外new selectlistiem的方式增加所以才出現錯誤?

你直接new給他

select new StViewModel
                         {
                             skill_id = s.skill_id,
                             org_id = e.org_id,
                             tag_name = t.tag_name,
                             skill_name = s.skill_name,
                             Scores_List =  new List<SelectListItem>()
{
     new SelectListItem { Value = "0", Text = "0", Selected = true },
     new SelectListItem { Value = "1", Text = "1", Selected = false }
};
                         }

Asd 大你好,昨天回覆上限滿了就沒回了,之後有成功但把你的@item.scores改成skill_id.tostring()。因為scores是null所以改掉。但成功後我發現我還是不知道這樣就能讓後端自己取到值了嗎?可能我還不夠熟Mvc。完成一個課題後現在要開始進入到取值存資料庫的課題。我現在是靠$( .table select).each(function (){$(this).attr(Id)+$(this).Val)取值。

透過MODEL BIDDING

//前端改成這樣
@for (int i = 0; i < Model.Count(); i++)
{
    @Html.DropDownList("Model[" + i + "].Scores", (IEnumerable<SelectListItem>)@Model[i].Scores_List);
}

@Model[i].Scores_List好像不能用會出現[]這個符號無法運用到stViewModel的運算式。很感謝asd這樣熱情的幫忙,但我現在可能要先研究如何db.savechange一次大筆的post方法我之前只有寫過如何取值還沒學如何存值@@

你可以查一下
bulk-save-changes
我抽空寫了一下 我這邊是可以的

無法套用有[]的索引至類型為IEnumerableStViewModel的運算式,好我等等查一下。目前的想法應該就是日後可以透過stViewModel把我前端的scores傳回Controller的post方法直接透過model的score接收分數就能完成更新應該是這樣吧?但這樣的話它怎麼知道我是選幾分

https://ithelp.ithome.com.tw/upload/images/20211101/20137303AabBpA5Ud1.pnghttps://ithelp.ithome.com.tw/upload/images/20211101/2013730307qRvIQVDF.pnghttps://ithelp.ithome.com.tw/upload/images/20211101/20137303PFBwAQ6ZH9.pnghttps://ithelp.ithome.com.tw/upload/images/20211101/20137303aQHNdPeTdw.pnghttps://ithelp.ithome.com.tw/upload/images/20211101/20137303PgWI2XkI0M.png

如圖
CSS我沒有調整
後端可以吃到的原因是因為MODEL BIDDING 建議你可以看一下
補一下後端Action
https://ithelp.ithome.com.tw/upload/images/20211101/20137303PDr2Ttx6Uj.png

我覺得可能是我最上面會先引用
@model IEnumerable WebMvc2.Models.StViewModel
的關係才會發生我的原因發生

@model IEnumerable<WebMvc2.Models.StViewModel>
<h2>IndexSt</h2>
<form style="margin-left:10px;" method="post" action="/Home/Update">
    <div class="row">
        <div class="col-lg-12">
            <table class="table table-hover">
                <tr>
                    <th>org id</th>
                    <th>tag name</th>
                    <th>skill name</th>
                    <th>評分項目</th>
                    <th></th>
                </tr>
                @foreach (var item in this.Model)
                {
                    <tr>
                        <td>@item.org_id</td>
                        <td>@item.tag_name</td>
                        <td>@item.skill_name</td>
                        <td>
                            @for (int i = 0; i < Model.Count(); i++)
                            {
                                @Html.DropDownList("Model[" + i + "].Scores", (IEnumerable<SelectListItem>)@Model[i].Scores_List);
                            }
                        </td>
                    </tr>
                }
            </table>
        </div>
    </div>
</form>

你要把FOREACH改成FOR
@for (int i = 0; i < Model.Count(); i++)

@item.org_id
@item.tag_name
@item.skill_name

@Html.DropDownList("Model[" + i + "].Scores", (IEnumerable)@Model[i].Scores_List);


}

對阿剛剛也有改成for的方式試過但還是一樣會有那個錯誤,因為我再用@Model[i].的時候也不會有給我提示字

@model IEnumerable<WebMvc2.Models.StViewModel>
<h2>IndexSt</h2>
<form style="margin-left:10px;" method="post" action="/Home/Update">
    <div class="row">
        <div class="col-lg-12">
            <table class="table table-hover">
                <tr>
                    <th>org id</th>
                    <th>tag name</th>
                    <th>skill name</th>
                    <th>評分項目</th>
                    <th></th>
                </tr>
                @for (int i=0;i<Model.Count();i++ )
                {
                    <tr>
                        <td>@Model[i].org_id</td>
                        <td>@Model[i].tag_name</td>
                        <td>@Model[i].skill_name</td>
                        <td>
                            @Html.DropDownList("Model[" + i + "].Scores", (IEnumerable)@Model[i].Scores_List);
                        </td>
                    </tr>
                }
            </table>
        </div>
    </div>
</form>

@Model 改成 this.Model

還是不行都會有無法套用有[]的索引至類型為IEnumerableStViewModel的運算式@@是因為我controller的FormInfo()沒有傳入StViewModel的關係嗎?

  [HttpPost]
        public ActionResult FormInfo(string emp_no, string org_id)
        {
            if (!string.IsNullOrWhiteSpace(emp_no) && (!string.IsNullOrWhiteSpace(org_id)))
            {
                var form = this.GetForm(emp_no, org_id);
                ViewData.Model = form;
            }
            return PartialView("_FormInfo");
        }

有可能 我只是提供解題思路 你可以自己多嘗試一下

好,因為我一開始學的時候有用你類似的方法但是包成viewbag的方式,然後ViewBag.OrgList也就單純放一個list所以可以count跟取得它的變數。但現在可能整包塞在model它無法辨識但也只是我的猜測

@{
    var orglist = ViewBag.OrgList;
}
form style="margin-left:10px;" method="post" action="">
    <div class="form-group">
        <label for="Org">部門</label>
        <select id="dep" name="dep">
            <option value="">請選擇</option>
            @for (int i = 0; i < orglist.Count; i++)
            {
                <option value="@orglist[i].org_id">@orglist[i].org_cname</option>
            }
        </select>
        <select id="emp" name="emp">
                <option value="">請選擇員工</option>
        </select>

    </div>
    <button type="submit" class="btn btn-primary">確定</button>
    <button type="reset" class="btn btn-info">清除</button>
</form>
0
小魚
iT邦大師 1 級 ‧ 2021-10-29 14:25:44

html的id應該是unique才對,
其實除了id還可以用其他方式處理,
name或click之類的,
事件可以使用this之類的,
或用綁定的,
這已經不是C#的問題,
而是JavaScript或JQuery的問題了,
我當初後端學JavaScript也學了一段時間.

這倒是真的,現在只是在想用C#還是JS哪一個能解決,目前就先都試試看以前用FINDCONTROL可以解決現在就要在學一下如何解決

Homura iT邦高手 1 級 ‧ 2021-10-29 15:25:47 檢舉

shen2255678
其實你這種複雜的table建議一定要用個table元件之類
或是一些js framework輔助
不然就算html helper做出來一定是很難用...

小魚 iT邦大師 1 級 ‧ 2021-11-01 10:24:37 檢舉

現在都傾向用前端,
對使用者體驗也比較好,
不過就要學一下js了,
或是像Homura大大說的,
如果能找到適合的套件,
用適合的套件比較快,
但是如果需要修改還是要會js,
(總之後端學到後來總是需要會js的)

我要發表回答

立即登入回答