2012-01-03 4 views
1

私は、ListBoxForと似たような魔法の仕組みでカスタムのhtml拡張メソッドを作成しようとしていますが、複数のチェックボックスの代わりにチェックボックスのグループをレンダリングしています。ListBoxForの代わりに出力チェックボックスのように機能するカスタムhtml拡張機能を作成しますか?

これについてはどのような方法がありますか? ListBoxForメソッドがどのように動作するかは、式とselectListItemsの列挙可能なものが渡されたときにどのように動作するのか不思議です。それはモデルを渡されていないので、どのように正しい項目を選択するのかをどうやって知ることができますか?また、匿名オブジェクトに基づいてhtml属性をどのように記述しますか?

答えて

2

あなたが達成しようとしているかのいずれかの詳細と具体的な例を提供していません。あなたはあなたが持っている問題を解決するためにこれまでに試したソースコードを提供していません。次回はStackOverflowの質問をしてください。あなたの質問をより意味深くし、特定の問題に集中させるためにしてください。

とにかく、ここに例があります。値で、このビューモデルを投入し、うまくいけば、POSTアクションでビューで選択された値を取得します

public class MyViewModel 
{ 
    public IEnumerable<string> SelectedValues { get; set; } 
    public IEnumerable<SelectListItem> Values { get; set; } 
} 

とコントローラ:

public class HomeController : Controller 
{ 
    public ActionResult Index() 
    { 
     var model = new MyViewModel 
     { 
      SelectedValues = new[] { "1", "3" }, 
      Values = new[] 
      { 
       new SelectListItem { Value = "1", Text = "item 1" }, 
       new SelectListItem { Value = "2", Text = "item 2" }, 
       new SelectListItem { Value = "3", Text = "item 3" }, 
      } 
     }; 
     return View(model); 
    } 

    [HttpPost] 
    public ActionResult Index(MyViewModel model) 
    { 
     // model.SelectedValues will contain the ids of items that were checked 
     // in the checkbox list 
    } 
} 

とあなたがビューモデルを定義していると仮定してみましょうビュー:

@model MyViewModel 

@using (Html.BeginForm()) 
{ 
    @Html.CheckBoxListFor(x => x.SelectedValues, Model.Values, null) 
    <button type="submit">OK</button> 
} 

OK、これまで良好でした。最後の部分はこのCheckBoxListForヘルパーを実装しようとすることです。明らかに、あなたの特定の要件や状況に応じて、これを行うための多くの可能な方法があります(回答の冒頭で私の発言を参照してください)。

public static class HtmlExtnsions 
{ 
    public static IHtmlString CheckBoxListFor<TModel, TProperty>(
     this HtmlHelper<TModel> htmlHelper, 
     Expression<Func<TModel, TProperty>> expression, 
     IEnumerable<SelectListItem> selectList, 
     object htmlAttributes 
    ) 
    { 
     var name = ExpressionHelper.GetExpressionText(expression); 
     string fullHtmlFieldName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name); 
     var values = GetModelStateValue(htmlHelper.ViewData, fullHtmlFieldName, typeof(string[])); 
     if (values == null) 
     { 
      values = htmlHelper.ViewData.Eval(fullHtmlFieldName); 
     } 

     if (values != null) 
     { 
      var collection = 
       from object value in values as IEnumerable 
       select Convert.ToString(value, CultureInfo.CurrentCulture); 
      var hashSet = new HashSet<string>(collection, StringComparer.OrdinalIgnoreCase); 
      var list = new List<SelectListItem>(); 
      foreach (var item in selectList) 
      { 
       item.Selected = ((item.Value != null) ? hashSet.Contains(item.Value) : hashSet.Contains(item.Text)); 
       list.Add(item); 
      } 
      selectList = list; 
     } 

     var sb = new StringBuilder(); 
     foreach (var item in selectList) 
     { 
      var checkbox = new TagBuilder("input"); 
      checkbox.Attributes["type"] = "checkbox"; 
      checkbox.Attributes["name"] = fullHtmlFieldName; 
      checkbox.Attributes["value"] = item.Value; 
      checkbox.GenerateId(fullHtmlFieldName); 
      if (item.Selected) 
      { 
       checkbox.Attributes["checked"] = "checked"; 
      } 
      sb.Append(checkbox.ToString(TagRenderMode.SelfClosing)); 
      sb.Append(item.Value); 
     } 

     return new HtmlString(sb.ToString()); 
    } 

    private static object GetModelStateValue(ViewDataDictionary viewData, string key, Type destinationType) 
    { 
     ModelState modelState; 
     if (viewData.ModelState.TryGetValue(key, out modelState) && modelState.Value != null) 
     { 
      return modelState.Value.ConvertTo(destinationType, null); 
     } 
     return null; 
    } 
} 
+1

申し訳ありませんが、私の質問はとても曖昧だったが、あなたの答えのためのおかげで、私はすでにそこから多くのことを学びました。だからここにあなたが始めることができ、単にいくつかのサンプル実装です。特に私はTagBuilderやhtmlHelper.ViewData.Evalについて知らなかった。 – zod

+0

@zod、ASP.NET MVCのソースコードを見ていないのですか?標準ヘルパーがどのように実装されているかを知るには、そうすることをお勧めします。フレームワークの理解を深め、カスタムヘルパーの実装を容易にすることができます。 –

+0

これはすべてのチェックボックスに同じIDを生成しますが、これは間違っているため、その1行を削除しました(とにかくIDが必要ないとは思わない)。また、html属性は使用しませんが、ほとんど必要なくなり、削除されました。そうでなければそれは優れています(私はdiv内のすべてのものをラップし、そのクラスに(ハードコードされています)(おそらく私もIDを与える必要があります)、ラベルのタグに各チェックボックスとテキストのペアを入れます)。どうもありがとう。 – zod

関連する問題