基本クラス、サブクラスのセット、およびコレクションコンテナがあり、部分ビューを使用してコントロールを動的に作成および設定するために使用しています。
// base class
public class SQControl
{
[Key]
public int ID { get; set; }
public string Type { get; set; }
public string Question { get; set; }
public string Previous { get; set; }
public virtual string Current { get; set; }
}
// subclass
public class SQTextBox : SQControl
{
public SQTextBox()
{
this.Type = typeof(SQTextBox).Name;
}
}
//subclass
public class SQDropDown : SQControl
{
public SQDropDown()
{
this.Type = typeof(SQDropDown).Name;
}
[UIHint("DropDown")]
public override string Current { get; set; }
}
// collection container used as the Model for a view
public class SQControlsCollection
{
public List<SQControl> Collection { get; set; }
public SQControlsCollection()
{
Collection = new List<SQControl>();
}
}
実行時に必要に応じて、コレクションコントロールにSQControlのさまざまなサブクラスを設定します。また、EditorTemplatesには、サブクラスごとに個別のビューがあります。コレクションアイテムでHtml.EditorForを使用すると、適切なコントロールを使用してフォームを動的に生成できます。
これはすべて正常に機能します。
私が抱えている問題は、フォームを保存するときに、MVCバインディングが、コレクション内の各アイテムがどのサブクラスで作成されたかを認識できず、代わりにそれらを基本クラスSQControlのインスタンスにバインドすることです。
これにより、ビューエンジンが混乱します。これは、ロードする適切なビューを決定できず、単にデフォルトをロードするためです。
現在の回避策は、サブクラスの「タイプ」をモデルのフィールドとして保存することです。ポストバック時に、コレクションを新しいコンテナーにコピーし、の情報に基づいて適切なサブクラスで各オブジェクトを再作成します。フィールドを入力します。
public static SQControlsCollection Copy(SQControlsCollection target)
{
SQControlsCollection newCol = new SQControlsCollection();
foreach (SQControl control in target.Collection)
{
if (control.Type == "SQTextBox")
{
newCol.Collection.Add(new SQTextBox { Current = control.Current, Previous = control.Previous, ID = control.ID, Question = control.Question });
}
else if (control.Type == "SQDropDown")
{
newCol.Collection.Add(new SQDropDown { Current = control.Current, Previous = control.Previous, ID = control.ID, Question = control.Question });
}
...
}
return newCol;
}
だから私の質問は、ポストバックの間にベースタイプのコレクション内のアイテムのタイプを維持するためのより良い方法はありますか?モデルごとに型付きビューを使用するのがMVCの慣例であることは理解していますが、再利用可能な部分ビューを使用してXMLドキュメントに基づいてその場でビューを構築できるようにしたいと考えています。