2012-07-14 12 views
11

ダイナミックプロパティを使用するエディタテンプレートを無駄に使用しようとしています。たぶんあなたの一人が私たちを助けることができます。Asp.Net MVC 3ダイナミックプロパティのエディタ

public class Criterion 
{ 
    ... 
    public string Text { get; set; } 
    public dynamic Value { get; set; } 
    public Type Type { get; set; } 
    ... 
} 

当社のかみそりビューは、それぞれがその中に基準のリストが含まれているセクションのリストをcontaingモデルを取得します。ここでは

は大体私たちのクラスです。 (私たちは、実行時にこれらに関する情報を取得します。)これらのすべての基準が編集モードで表示されなければならない - 彼らの実際の型に関する:(抜粋)

@for (int i = 0; i < model.Sections.Count(); i++) 
{ 
    for (int j = 0; j < model.Sections[i].Criteria.Count(); j++) 
    { 
     var criterion = model.Sections[i].Criteria[j]; 
     var type = criterion.Type.Name; 
     var name = "Sections[" + i + "].Criteria[" + j + "].Value"; 
     var criterionDisplayName = criterion.Text; 
     <label for="[email protected](i)[email protected](j)__Value">@criterionDisplayName</label> 
     @Html.Editor(name, type) 
    } 
} 

これは正しくインスタンスのチェックボックスを表示していますが、それが値を使用していませんチェックボックスのステータスを正しく設定します(criterion.Valueがtrueの場合にチェックされます)。 intsのように他のタイプにも同じです。 (POSTリクエスト後にフォームに正しく入力されますが、これはMVCが一時的なモデルを使用してユーザーの入力を再作成するためです)。

私たちが試してみた限りでは、エディタタイプdynamicのプロパティを持つテンプレート?はいの場合 - どのように機能させることができますか? (実際のタイプに基づいて適切なエディタテンプレートを使用するようMVCフレームワークを使用したいと考えています)

答えて

15

ダイナミクスはASP.NETでうまく収まりませんMVC。彼らはViewBagについて私に思い出させ、私はViewBagが私の体の非常に深い織物から嫌いです。だから私は別のアプローチをとるだろう。

のは、例えば次のようなモデルを見てみましょう:

public class Criterion 
{ 
    public string Text { get; set; } 
    public object Value { get; set; } 
} 

値は、あなたが扱うことを望む任意の型である可能性があります。あなたは、対応するエディタを定義することができます処理したい各タイプのための今すぐ

@model IList<Criterion> 

@using (Html.BeginForm()) 
{ 
    for (int i = 0; i < Model.Count; i++) 
    { 
     <div> 
      @Html.LabelFor(x => x[i], Model[i].Text) 
      @Html.EditorFor(x => x[i].Value, "Criterion_" + Model[i].Value.GetType().Name) 
     </div> 
    } 

    <button type="submit">OK</button> 
} 

public class HomeController : Controller 
{ 
    public ActionResult Index() 
    { 
     var model = new[] 
     { 
      new Criterion { Text = "some integer", Value = 2 }, 
      new Criterion { Text = "some boolean", Value = true }, 
      new Criterion { Text = "some string", Value = "foo" }, 
     }; 
     return View(model); 
    } 
} 

してから対応するビュー:

は今、あなたはこのモデルを移入コントローラを持つことができますテンプレート:

~/Views/Shared/EditorTemplates/Criterion_String.cshtml

~/Views/Shared/EditorTemplates/Criterion_Boolean.cshtml

@model bool 
@Html.CheckBoxFor(x => x) 

~/Views/Shared/EditorTemplates/Criterion_Int32.cshtml:明らかに鑑みて、このモデルを表示

@model int 
@{ 
    var items = Enumerable 
     .Range(1, 5) 
     .Select(x => new SelectListItem 
     { 
      Value = x.ToString(), 
      Text = "item " + x 
     }); 
} 

@Html.DropDownListFor(x => x, new SelectList(items, "Value", "Text", Model)) 

は、最初のステップです。私はあなたがいくつかの処理のためにPOSTコントローラのアクションで戻った値を取得したいと思うでしょう。この場合、いくつかの小さな適応が必要です。実行時に正しい型をインスタンス化し、各行の隠しフィールドとして具体的な型を含めることができるカスタムモデルバインダーを追加する必要があります。私はすでにthis postに例を示しました。この例では、直接objectタイプで作業するのではなく、基本クラスを使用していることにも注意してください。

+0

強く型付けされたビューで動作します。強く型付けされたビューを使わないようにIndex-Viewを変更しようとしました: '@model IList 'を削除し、 '@ {var model =(IList )Model; } '。それから、@Html.Editor( "model" "+ i +"] .Value "、" Criterion_ "+ model [i] .Value.GetType()。Name)'を試してみましたが、エラーが出ます - _モデル辞書に渡された項目はnullですが、この辞書は 'System.Int32'型のnull以外のモデル項目を必要とします。何が間違っていますか?デバッグはGetType()。NameがIndex-Viewで 'Int32'であることを示しています。 – toni

+0

ところで、私たちは第三者フレームワーク(OrchardのContentShape)を使用しているので、強く型付けされていないビューを使用する必要があります。 – toni

+0

上記のように 'object'を使ってDarinsアプローチを使用しました。動的ViewModelをキャストして強く型付けされたエディタテンプレートに渡すだけでした。貴重な情報をいただきありがとうございます。 – toni