2012-01-17 9 views
0

このすばらしい回答http://bit.ly/Aevcea(下のコード)のおかげで、HtmlHelperでCheckBoxListFor拡張機能をビルドしましたが、期待通りに投稿できません。MVC CheckBoxListFor予想通りに投稿していません

私のフォームは、(他のプロパティの中で)string Nameとint [] PersonIDを持つモデルグループに基づいています。私のコントローラは、このフォームの送信を処理するために、編集(グループグループ)メソッドを持ってい

<ul> 
    <li><input type="checkbox" name="PersonIDs" value="1" id="PersonIDs_1" /></li> 
    <li><input type="checkbox" name="PersonIDs" value="2" id="PersonIDs_2" /></li> 
</ul> 

CheckBoxListForはこのような何かをレンダリングします。しかし、提出すると、group.PersonIDsがnullであることがわかります。 Request.Form ["PersonIDs"]は選択された値に設定されています(上記の両方の項目がチェックされている場合は "1,2"など)。また、Editメソッド(int [] PersonIDs)に別のパラメータを追加すると、期待される内容(選択されたID)で到着します。

誰も私が間違っていることを説明できますか?私の編集方法でグループパラメータは、フォームに従って設定名で戻って来ないことを

@Html.TextBoxFor(m => m.Group.Name) 
@Html.CheckBoxListFor(m => m.Group.PersonIDs, Model.MultiSelectListOfAllPeople) 

注:私のビューの関連ビットは、この(余分なビットが取り除か)のように見えます。

ただ完全を期すために、ここに私のCheckBoxListFor拡張のフルボディは、次のとおりです。

public static MvcHtmlString CheckBoxListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, IEnumerable<TProperty>>> expression, MultiSelectList multiSelectList, object htmlAttributes = null) 
{ 
    //Derive property name for checkbox name 
    MemberExpression body = expression.Body as MemberExpression; 
    string propertyName = body.Member.Name; 

    //Get currently select values from the ViewData model 
    IEnumerable<TProperty> list = expression.Compile().Invoke(htmlHelper.ViewData.Model); 

    //Convert selected value list to a List<string> for easy manipulation 
    List<string> selectedValues = new List<string>(); 

    if (list != null) 
    { 
     selectedValues = new List<TProperty>(list).ConvertAll<string>(delegate(TProperty i) { return i.ToString(); }); 
    } 

    //Create div 
    TagBuilder wrapper = new TagBuilder("ul"); 
    wrapper.AddCssClass("clearfix"); 
    wrapper.MergeAttributes(new RouteValueDictionary(htmlAttributes), true); 

    //Add checkboxes 
    foreach (SelectListItem item in multiSelectList) 
    { 
     wrapper.InnerHtml += String.Format("<li><input type=\"checkbox\" name=\"{0}\" id=\"{0}_{1}\" " + 
              "value=\"{1}\" {2} /><label for=\"{0}_{1}\">{3}</label></li>", 
              propertyName, 
              item.Value, 
              selectedValues.Contains(item.Value) ? "checked=\"checked\"" : "", 
              item.Text); 
    } 

    return MvcHtmlString.Create(wrapper.ToString()); 
} 

答えて

1

OK、問題がCheckBoxListFor拡張子がGroup.PersonIDsではなく、単にPersonIDsとしてコントロール名をレンダリングするために必要なことでした。フォームは、それ自体がビューモデルのサブプロパティであったオブジェクトにバインドされていました。私はすぐに次のように私のCheckBoxListForメソッドを適合させましたが、より洗練されたソリューションを受け入れることに感謝します!私はIDに宣言型の名前を含めるかどうかを指示する追加のブール型パラメータのincludeDeclaringTypeを渡しています。これが他の方法で推測できるのかどうかは分かりません。あなたはまた、ExpressionHelper.GetExpressionTextメソッドを使用することができます

public static MvcHtmlString CheckBoxListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, IEnumerable<TProperty>>> expression, MultiSelectList multiSelectList, bool includeDeclaringType, object htmlAttributes = null) 
    { 
     //Derive property name for checkbox name 
     MemberExpression body = expression.Body as MemberExpression; 
     string declaringTypeName = body.Member.DeclaringType.Name; 
     string propertyName = body.Member.Name; 

     //Get currently select values from the ViewData model 
     IEnumerable<TProperty> list = expression.Compile().Invoke(htmlHelper.ViewData.Model); 

     //Convert selected value list to a List<string> for easy manipulation 
     List<string> selectedValues = new List<string>(); 

     if (list != null) 
     { 
      selectedValues = new List<TProperty>(list).ConvertAll<string>(delegate(TProperty i) { return i.ToString(); }); 
     } 

     //Create div 
     TagBuilder wrapper = new TagBuilder("ul"); 
     wrapper.AddCssClass("clearfix"); 
     wrapper.MergeAttributes(new RouteValueDictionary(htmlAttributes), true); 

     //Add checkboxes 
     foreach (SelectListItem item in multiSelectList) 
     { 
      var name = string.Concat(
       includeDeclaringType ? string.Format("{0}.", declaringTypeName) : "", 
       propertyName 
      ); 

      var id = string.Concat(
       includeDeclaringType ? string.Format("{0}_", declaringTypeName) : "", 
       propertyName, 
       "_", 
       item.Value 
      ); 

      wrapper.InnerHtml += String.Format("<li><input type=\"checkbox\" name=\"{0}\" id=\"{1}\" " + 
               "value=\"{2}\" {3} /><label for=\"{1}\">{4}</label></li>", 
               name, 
               id, 
               item.Value, 
               selectedValues.Contains(item.Value) ? "checked=\"checked\"" : "", 
               item.Text); 
     } 

     return MvcHtmlString.Create(wrapper.ToString()); 
    } 
0

、それはあなたのための正しい入力された名前が生成されます。

var expressionText = ExpressionHelper.GetExpressionText(expression); 

wrapper.InnerHtml += 
     string.Format("<li><input type=\"checkbox\" name=\"{0}" id=\"{0}_{1}\" " + 
         "value=\"{1}\" {2} /><label for=\"{0}_{1}\">{3}</label></li>", 
         expressionText, 
         item.Value, 
         selectedValues.Contains(item.Value) ? "checked=\"checked\"" : "", 
         item.Text); 
+0

をありがとう@nativehr - 私は本当に答えとしてこれをマークすることはできませんが、それは本当にです役に立つ情報 – getsetcode

関連する問題