私はなんとか何かを理解することができました。私の問題はあなたが持っているものとまったく同じではありませんが、確かにあなたを助けることができます. しかし、まず最初に。
問題
いくつかのコントロールがあります (私の場合は部分ビューです)。例えば:
Views/Shared/EditName.cshtml
Views/Shared/EditAddress.cshtml
Views/Shared/EditEmail.cshtml
Views/Shared/EditFavoriteColour.cshtml
これらのコントロールのグループを (データベースまたは web.config で) 定義したいと考えています。たとえば、次のようになります。
SimpleEditGroup:
EditName
ExtendedEditGroup:
EditName
EditEmail
FullEditGroup:
EditName
EditAddress
EditEmail
EditFavoriteColour
次に、特定のグループに基づいてビューをレンダリングしたいと考えています。次の構文で十分だと思っていました。
@Html.Partial("ControlGroup:ExtendedEditGroup", Model)
ソリューションのドラフト
私は、次のことを行う独自のレンダリング エンジンを作成したいと考えていました。
- ビューの名前が「ControlGroup:」で始まる場合は、以前に定義したグループを使用してページをレンダリングします。各コントロールは、RazorViewEngine によってレンダリングされる必要があります。
- ビューの名前が "ControlGroup:" で始まらない場合は、RazorViewEngine に任せてください。
リサーチ
次のリソースを見つけました。
- CodeProject に関する記事 - ASP.NET MVC3 のカスタム ViewEngine
- StackOverflow の質問に基づく記事 - ASP.NET MVC 3 でのウィジェット システムの作成
- 本Pro ASP.NET MVC 3 Frameworkをお勧めします。ASP.NET MVC 3 でカスタマイズできる項目の数がわかります。
- もちろん、ASP.NET MVC 3 RTMのソース コードは非常に役に立ちました。
最終的解決
MyViewEngine:
public class MyViewEngine : RazorViewEngine
{
IDictionary<string, List<string>> groups = new Dictionary<string, List<string>>();
public MyViewEngine()
{
// Temporary data source
groups["SimpleEditGroup"] = new List<string>() { "EditName"};
groups["ExtendedEditGroup"] = new List<string>() { "EditName", "EditEmail"};
}
public override ViewEngineResult FindView(ControllerContext controllerContext,
string viewName, string masterName, bool useCache)
{
if (viewName.StartsWith("ControlGroup"))
{
var groupName = viewName.Split(':')[1];
var controls = new List<ViewEngineResult>();
foreach (var controlName in groups[groupName])
{
// Find each control using Razor magic
var control = base.FindPartialView(controllerContext, controlName, useCache);
if (control.View != null)
{
controls.Add(control);
}
}
if(controls.Count > 0)
return new ViewEngineResult(new MyView(controls), this);
}
return base.FindView(controllerContext, viewName, masterName, useCache);
}
}
MyView.cs:
public class MyView : IView
{
IList<ViewEngineResult> controls;
public MyView(IList<ViewEngineResult> _controls)
{
controls = _controls;
}
public void Render(ViewContext viewContext, TextWriter textWriter)
{
// For simplicity I used table for layout
textWriter.Write("<table border='1'>");
foreach (var ctrl in controls)
{
textWriter.Write("<tr><td>");
// Render control using Razor
ctrl.View.Render(viewContext, textWriter);
textWriter.Write("</td></tr>");
}
textWriter.Write("</table>");
}
}
新しいエンジンを Global.asax に登録することを忘れないでくださいViewEngines.Engines.Add(new MyViewEngine());
ハッピーエンド
これは 2 つの方法で使用できます。コントローラーを使用してビューに埋め込むか、コントローラーからRender.Partial
単に返すことです。PartialView
それがあなたを助けるかどうか私に知らせてください。また、ソリューションを共有することもできます。