2016-06-01 8 views
0

SQLテーブルからリスト<を取得するページを作成して表示し、ユーザーが変更できるようにします。私はすでに情報を表示することができます。私はそれを提出することに問題が発生しています。私は入力されたデータを受け取り、変更をリスト<に送信する方法を考え出すことができないので、コントローラ/モデルでそれを操作することができます。C#MVCは、1つのモデルを使用してビューとの間でリストを送受信します。

現在、私は提出時に新しいデータを配列に配置しています。ビューでは@model List<modelname>を使用しているので値を置き換えたり、データをビューから新しいリストに入れることは可能ですか?

答えて

0

あなたはこれを絶対に行うことができますが、当初は問題に遭遇する傾向がありますので、完全な例を示します。

public class HomeController : Controller 
{ 
    public ActionResult Index() 
    { 
     // Assume this would really come from your database. 
     var employees = new List<EmployeeViewModel>() 
     { 
      new EmployeeViewModel { Id = 1, Name = "Employee 1" }, 
      new EmployeeViewModel { Id = 2, Name = "Employee 2" }, 
      new EmployeeViewModel { Id = 3, Name = "Employee 3" }, 
     }; 

     return View(employees); 
    } 

    [HttpPost] 
    public ActionResult Index(List<EmployeeViewModel> employees) 
    { 
     // Rest of action 
    } 
} 

人が最初にこの問題にアプローチの典型的な方法は、index.cshtmlで、次のような何かをすることです:

のは、 List<EmployeeViewModel>を返す Index作用を有する HomeControllerを定義してみましょう、で開始する

@model List<EmployeeViewModel> 

@using (Html.BeginForm()) 
{ 
    foreach (var item in Model) 
    { 
     <div class="row"> 
      @Html.EditorFor(x => item.Id) 
     </div> 
     <div class="row"> 
      @Html.EditorFor(x => item.Name) 
     </div> 
    } 

    <input type="submit" /> 
} 

一見、これはうまくいくように見えます。ただし、POSTアクションにブレークポイントを設定して[送信]ボタンをクリックすると、employeesnullになります。私はそこにいくつかの無関係な部分を取り除いてきた

<input name="item.Id" type="number" value="1" /> 
<input name="item.Name" type="text" value="Employee 1" /> 
<input name="item.Id" type="number" value="2" /> 
<input name="item.Name" type="text" value="Employee 2" /> 
<input name="item.Id" type="number" value="3" /> 
<input name="item.Name" type="text" value="Employee 3" /> 

が、name属性は各従業員の同じ値を持っているかがわかりますforeachループは以下のようなHTMLを生成しているため、そのための理由があります。デフォルトのモデルバインダーがサーバー上のデータのリストを構築しようとすると、異なる従業員を区別することができなければならず、そうではないため、リストはnullになります。

なぜ同じ値を生成していますか?それは、このためです:

@Html.EditorFor(x => item.Id) 
@Html.EditorFor(x => item.Name) 

情報が生成されたHTMLにそれを作るしないように私たちは、HtmlHelperメソッド呼び出しにインデックス値を渡していません。私たちは今、各メソッド呼び出しでインデックスを供給していたよう

for (int i = 0; i < Model.Count; i++) 
{ 
    @Html.EditorFor(x => Model[i].Id) 
    @Html.EditorFor(x => Model[i].Name) 
} 

、生成されたHTMLは現在、各従業員のためのインデックスが含まれていない:私たちは、単に代わりforループを利用することによってこの問題を解決することができ

<input name="[0].Id" type="number" value="1" /> 
<input name="[0].Name" type="text" value="Employee 1" /> 
<input name="[1].Id" type="number" value="2" /> 
<input name="[1].Name" type="text" value="Employee 2" /> 
<input name="[2].Id" type="number" value="3" /> 
<input name="[2].Name" type="text" value="Employee 3" /> 

デフォルトのモデルバインダーではIdNameをそれぞれEmployeeViewModelに関連付けて、サーバー上で型を正しく構築できます。

この時点で問題は解決されますが、避けることができる場合はforループを使用することは推奨されません。これによりエディタテンプレートが表示されます。エディタテンプレートはHtmlHelperのメソッドで、指定されたタイプのカスタムテンプレート(ビュー)をレンダリングできます。そこで、上記の例のコードを使用してそれを行う方法の例を示します。で開始する

、次の手順を実行する必要があります:

  1. EditorTemplates名前はMVCで特別な意味を持っているので、それはそれを正しくスペルすることが重要です)あなたの~/Views/Home/フォルダ内EditorTemplatesフォルダを作成します。 。
  2. このフォルダ内にEmployeeViewModel.cshtmlビューを作成します(ここでも重要なのは、カスタムテンプレートを作成するタイプの名前と一致する必要があります)。 、今

    Editor templates example

    EmployeeViewModel.cshtmlを開き、その中Index.csから、あなたのレンダリングコードを置く:あなたはそれをやった後は

、それは次のようになります

@model EmployeeViewModel 

<div class="row"> 
    @Html.EditorFor(x => x.Id) 
</div> 
<div class="row"> 
    @Html.EditorFor(x => x.Name) 
</div> 

最後にindex.cshtmlを開き、次のように変更します。

、およびHtml.DisplayFor、彼らはコレクションのために呼び出されているときに認識できるほど賢く両方なので、この場合には(コレクションのタイプをレンダリングするカスタムテンプレートを探し、EditorForは、エディタのテンプレートを探しますEmployeeViewModel)。

エディタテンプレートを用意したので、コレクション内の各アイテムに対してレンダリングするだけでなく、モデルバインダーに再構築に必要なすべての情報を与える、それぞれのアイテムの正しいインデックスも生成しますサーバー上のそのコレクション。

最終的には、モデルのバインディングが簡単になり、ビューのコードが簡単になるだけでなく、関連するタイプに基づいて分割されるため、ビューの操作が簡単になります。すべてを行う巨大な眺め。

私の例ではコレクションを直接使用しているので、実際に@Html.EditorFor(x => x)@Html.EditorForModel()に置き換えることもできます。私は最初にそれをしませんでした。なぜなら、後者を使ってテンプレートを呼び出すという印象を与えたくないからです。

+1

ああ!どうもありがとうございます!! –

+0

@ HarporSydneyようこそ。 :) –

関連する問題