2011-02-03 17 views
12

ここでは、モデルにポストバックが発生したときにチェックボックスリスト項目のリストをバインドする方法を簡単に見つける方法を探しています。チェックボックスリストをasp.net mvcのモデルにバインドする方法はありますか

明らかにこれを行う一般的な方法は、このようにしているようです。form.GetValues("checkboxList")[0].Contains("true");これは痛みを伴うものであり、正確には安全ではないようです。

の内側IList<string>またはstring[]を埋めるだろう(またはビューのヘルパーせずに作成されている)チェックボックスのリストまたはUpdateModel(myViewModel, form.ToValueProvider());フェーズでも、そのためのデータの配列事項をバインドする方法はありますモデル?

答えて

9

あなたはモデルで始めることができます:

public class MyViewModel 
{ 
    public int Id { get; set; } 
    public bool IsChecked { get; set; } 
} 

コントローラ:

public class HomeController : Controller 
{ 
    public ActionResult Index() 
    { 
     var model = new[] 
     { 
      new MyViewModel { Id = 1, IsChecked = false }, 
      new MyViewModel { Id = 2, IsChecked = true }, 
      new MyViewModel { Id = 3, IsChecked = false }, 
     }; 
     return View(model); 
    } 

    [HttpPost] 
    public ActionResult Index(IEnumerable<MyViewModel> model) 
    { 
     // TODO: Handle the user selection here 
     ... 
    } 
} 

ビュー(~/Views/Home/Index.aspx):

<% using (Html.BeginForm()) { %> 
    <%=Html.EditorForModel() %> 
    <input type="submit" value="OK" /> 
<% } %> 

そして最後に、対応するエディタテンプレート:

<%@ Control 
    Language="C#" 
    Inherits="System.Web.Mvc.ViewUserControl<AppName.Models.MyViewModel>" %> 
<%= Html.HiddenFor(x => x.Id) %> 
<%= Html.CheckBoxFor(x => x.IsChecked) %> 

POSTアクションでフォームを送信すると、選択された値のリストがIDとともに取得されます。

+0

アイデアは悪くないですが、これ以外の項目にフォームを使用する場合、それは動作しません。たとえば、ユーザー名/パスワード+チェックボックスのコレクションがあるとします。この方法では動作しません。/ – Erick

+2

@エリック、もちろん動作することができます。あなたのビューモデルは、 'Username'や' Password'のような単純なプロパティと、チェックボックス情報を含むコレクションプロパティIEnumerable を含んでいます。あなたのフォームに 'Html.EditorForModel'を使用するのではなく、単純な' <%= Html.TextBoxFor(x => x.Username)%> 'と' <%= Html.PasswordFor(x => x.Password) %> 'と、同じエディタテンプレートをレンダリングする' <%= Html.EditorFor(x => x.MyCheckboxes)%> 'となります。 –

+0

私はこれを達成するための多くの方法を読んでおり、これははるかにエレガントな解決策でした。ありがとう! – JimDaniel

9

ここはすばやく簡単です。 入力要素内にvalue属性を設定し、すべて同じnameを指定してください。お使いのコントローラで

<% using (Html.BeginForm()) { %> 
    <p><input type="checkbox" name="checkboxList" value="Value A" /> Value A</p> 
    <p><input type="checkbox" name="checkboxList" value="Value B" /> Value B</p> 
    <p><input type="checkbox" name="checkboxList" value="Value C" /> Value C</p> 
    <p><input type="checkbox" name="checkboxList" value="Value D" /> Value D</p> 
    <p><input type="checkbox" name="checkboxList" value="Value E" /> Value E</p> 
    <p><input type="checkbox" name="checkboxList" value="Value F" /> Value F</p> 
    <input type="submit" value="OK" /> 
<% } %> 

::私はサイトでこれを実装した場合、私は必要なだけのHTMLで表示しnamevalueisCheckedパラメータがかかりますが、ここにありCheckBoxヘルパーメソッドを作成します

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Index(IEnumerable<string> checkboxList) 
{ 
    if (checkboxList != null) 
    { 
     ViewData["Message"] = "You selected " + checkboxList.Aggregate("", (a, b) => a + " " + b); 
    } 
    else 
    { 
     ViewData["Message"] = "You didn't select anything."; 
    } 

    return View(); 
} 

IEnumerable<string>パラメータ(必要に応じてIList<string>にすることができます)には、チェックされた項目の値のみが含まれます。どのボックスもチェックされていなければ、nullになります。

+0

ユーザーがモデルをチェックボックス – tugberk

+0

@tugberkにバインドしたい場合は、痛みが伴うので、ネイティブのHTMLコードを置くのは良い考えではないと思います。プロダクションコードでヘルパーメソッドを使用すると言いました。私はちょうど元の質問への答えを表示しようとしていた。ヘルパーメソッドコードを追加します。 – CoderDennis

+2

これは正解です。組み込みの 'Html.CheckBox()'ヘルパーを使用しようとすると、隠しフィールドを 'value =" false "'で挿入しようとしているので、モデルバインドを妨げます。 – Yuck

0

このカスタムモデルバインダーと通常のHTMLを使用して、かなりうまく機能...

まず、カミソリの構文で、あなたのHTMLフォーム:

@using (Html.BeginForm("Action", "Controller", FormMethod.Post)) { 
    <ol> 
     <li><input type="textbox" name="tBox" value="example of another form element" /></li> 

     <li><input type="checkbox" name="cBox" value="1" /> One</li> 
     <li><input type="checkbox" name="cBox" value="2" /> Two</li> 
     <li><input type="checkbox" name="cBox" value="3" /> Three</li> 
     <li><input type="checkbox" name="cBox" value="4" /> Four</li> 
     <li><input type="checkbox" name="cBox" value="5" /> Five</li> 

     <li><input type="submit" /></li> 
    </ol> 
} 

FormMethod.Post.Get可能性があり、重要ではありません。

続い)このために、適切なMVCの意味で自分のフォームの送信を表すモデルオブジェクトを持っています210

カスタムモデルのバインダークラス(これはバインディングされたモデルの内側に配置したいので、上に作成したモデルを繰り返して、どこに追加するかを示します。また、)良いことですこれは、バインダーは、私有財産のセッターを使用することができます内側に配置すると:

public class CheckboxListExampleModel { 
    public string TextboxValue { get; private set; } 
    public List<int> CheckboxValues { get; private set; } 

    public class Binder : DefaultModelBinder { 
     public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { 
      var model = new CheckboxListExampleModel(); 

      model.TextboxValue = bindingContext.GetValueAsString("tBox"); 

      string checkboxCsv = bindingContext.GetValueAsString("cBox"); 
      // checkboxCsv will be a comma-separated list of the 'value' attributes 
      // of all the checkboxes with name "cBox" which were checked 
      model.CheckboxValues = checkboxCsv.SplitCsv<int>(); 

      return model; 
     } 
    } 
} 

.GetValueAsString()は、明確にするために使用される拡張メソッドである、ここにある:

public static string GetValueAsString(this ModelBindingContext context, string formValueName, bool treatWhitespaceAsNull = true) { 
     var providerResult = context.ValueProvider.GetValue(formValueName); 
     if (providerResult.IsNotNull() && !providerResult.AttemptedValue.IsNull()) { 
      if (treatWhitespaceAsNull && providerResult.AttemptedValue.IsNullOrWhiteSpace()) { 
       return null; 
      } else { 
       return providerResult.AttemptedValue.Trim(); 
      } 
     } 
     return null; 
    } 

.SplitCsv<T>()ですまた拡張メソッドですが、これは一般的な十分な必要性と私はそれを読者のための練習として残してくれる十分なコードです。

そして最後に、あなたの行動は、フォーム送信処理する:

[HttpPost] 
public ActionResult Action([ModelBinder(typeof(CheckboxListExampleModel.Binder))] CheckboxListExampleModel model) { 
    // stuff 
} 
関連する問題