如何在 ASP.NET MVC 中创建可重复使用的自定义 HTML 面板?
How can I create a re-usable custom HTML panel in ASP.NET MVC?
我正在尝试在 ASP.NET MVC 中创建一个可重复使用的 UI 元素,它环绕着我选择放置在其中的任何内容。我的第一个想法是创建一个局部视图,但这似乎对我想要完成的事情没有帮助。
模板
例如,我想创建一些与此类似的可重用标记(请原谅伪代码):
<div class="panel panel-default">
<div class="panel-body">
@RenderBody()
</div>
</div>
一个简单的例子
那么在我看来我想做类似这样的事情:
@Render.Partial("MyPanel")
{
<img src="image.jpg" />
}
假设代码按预期工作,它将生成以下内容:
<div class="panel panel-default">
<div class="panel-body">
<img src="image.jpg" />
</div>
</div>
另一个示例,带有更复杂的标记
从理论上讲,我希望能够将我想要的任何内容放置在其中一个面板中。因此,即使是更复杂的标记仍然清晰可见。
@Render.Partial("MyPanel")
{
<form>
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" class="form-control" id="exampleInputEmail1" placeholder="Enter email">
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
<input type="password" class="form-control" id="exampleInputPassword1" placeholder="Password">
</div>
<div class="form-group">
<label for="exampleInputFile">File input</label>
<input type="file" id="exampleInputFile">
<p class="help-block">Example block-level help text here.</p>
</div>
<div class="checkbox">
<label>
<input type="checkbox"> Check me out
</label>
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
}
就像第一个示例一样,它会将所有内容包装在我的模板的页眉和页脚中:
<div class="panel panel-default">
<div class="panel-body">
<form>
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" class="form-control" id="exampleInputEmail1" placeholder="Enter email">
</div>
.. truncated ..
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
</div>
已知的可能性
- 局部视图。局部视图似乎很有意义,除了我一直无法找到一种方法来创建一个局部视图,该局部视图具有超出其设计的模型的灵活性.我举了两个例子,因为我每次使用时面板中的内容可能会有很大不同。我希望能够将任何东西放入这个部分视图的主体中;文本、标记、更多剃须刀代码等
- HTML Helper. 当我有特定的参数时,这很好用。当需要输入大量数据时,我认为这不实用标记,因为它变得很难 read/maintain。此外,由于 html 将作为字符串传递,我不确定这将如何与 razor 标签一起使用?
- 2 个部分视图。 使用一个作为页眉,另一个作为页脚。这行得通,但对我来说就是草率。
我能够通过创建自定义控件在 ASP.NET WebForms 中做到这一点。这似乎在 MVC 中也应该是直截了当的事情,但我还没有完全能够找到一个好的解决方案。
在 MVC 中创建可重用内容的方法有很多,但它们各有利弊。例如,自定义 Html 帮助程序是一种常用方法,但它们需要编写的代码比您可能想要的要多得多。
您当然可以使用分部视图,只需将包含您要呈现的内容的模型传递给分部...但这也可能有点令人困惑。
我想您正在寻找的可能是 Razor Helpers。这些在此处有更详细的解释:
http://weblogs.asp.net/scottgu/asp-net-mvc-3-and-the-helper-syntax-within-razor
但是,基本结构如下所示:
@helper MyHelper(string content)
{
<div class="panel panel-default">
<div class="panel-body">
@Html.Raw(content)
</div>
</div>
}
然后你这样使用它:
@MyHelper("<img src="image.jpg" />")
你不必使用字符串,你可以使用结构化内容、模型等。你可以在里面使用其他帮助器。您可以按照本文后面的描述重新使用它们。
但是,您可能想要开始考虑将您的页面更多地以数据为中心。如果您使用 EditorTemplates 呈现您的数据,那么您将根据您的数据类型呈现控件,而不是呈现您的页面并尝试调整您的页面以包含您的数据。
您可以使用 "DynamicInvoke" 创建带有动态标记的 html 助手,例如:
public static IHtmlString CustomPanel(this HtmlHelper htmlHelper, Func<object, object> panelMarkup = null)
{
return CustomPanel(htmlHelper, (panelMarkup == null ? "" : panelMarkup.DynamicInvoke(htmlHelper.ViewContext).ToString()));
}
public static IHtmlString CustomPanel(this HtmlHelper htmlHelper, string content)
{
TagBuilder div = new TagBuilder("div");
div.AddCssClass("panel panel-default");
TagBuilder innerDiv = new TagBuilder("div");
innerDiv.AddCssClass("panel-body");
innerDiv.InnerHtml = content;
div.InnerHtml = innerDiv.ToString();
return new HtmlString(div.ToString());
}
然后你会像这样使用它:
@Html.CustomPanel(
@<text>
<div>My Custom Markup</div>
<span>More Stuff</span>
</text>
)
您的最终内容将如下所示:
<div class="panel panel-default">
<div class="panel-body">
<div>My Custom Markup</div>
<span>More Stuff</span>
</div>
</div>
你看到这个在一些第 3 方小部件库中经常使用(kendo-ui 是我所知道的主要的)
我正在尝试在 ASP.NET MVC 中创建一个可重复使用的 UI 元素,它环绕着我选择放置在其中的任何内容。我的第一个想法是创建一个局部视图,但这似乎对我想要完成的事情没有帮助。
模板
例如,我想创建一些与此类似的可重用标记(请原谅伪代码):
<div class="panel panel-default">
<div class="panel-body">
@RenderBody()
</div>
</div>
一个简单的例子
那么在我看来我想做类似这样的事情:
@Render.Partial("MyPanel")
{
<img src="image.jpg" />
}
假设代码按预期工作,它将生成以下内容:
<div class="panel panel-default">
<div class="panel-body">
<img src="image.jpg" />
</div>
</div>
另一个示例,带有更复杂的标记
从理论上讲,我希望能够将我想要的任何内容放置在其中一个面板中。因此,即使是更复杂的标记仍然清晰可见。
@Render.Partial("MyPanel")
{
<form>
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" class="form-control" id="exampleInputEmail1" placeholder="Enter email">
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
<input type="password" class="form-control" id="exampleInputPassword1" placeholder="Password">
</div>
<div class="form-group">
<label for="exampleInputFile">File input</label>
<input type="file" id="exampleInputFile">
<p class="help-block">Example block-level help text here.</p>
</div>
<div class="checkbox">
<label>
<input type="checkbox"> Check me out
</label>
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
}
就像第一个示例一样,它会将所有内容包装在我的模板的页眉和页脚中:
<div class="panel panel-default">
<div class="panel-body">
<form>
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" class="form-control" id="exampleInputEmail1" placeholder="Enter email">
</div>
.. truncated ..
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
</div>
已知的可能性
- 局部视图。局部视图似乎很有意义,除了我一直无法找到一种方法来创建一个局部视图,该局部视图具有超出其设计的模型的灵活性.我举了两个例子,因为我每次使用时面板中的内容可能会有很大不同。我希望能够将任何东西放入这个部分视图的主体中;文本、标记、更多剃须刀代码等
- HTML Helper. 当我有特定的参数时,这很好用。当需要输入大量数据时,我认为这不实用标记,因为它变得很难 read/maintain。此外,由于 html 将作为字符串传递,我不确定这将如何与 razor 标签一起使用?
- 2 个部分视图。 使用一个作为页眉,另一个作为页脚。这行得通,但对我来说就是草率。
我能够通过创建自定义控件在 ASP.NET WebForms 中做到这一点。这似乎在 MVC 中也应该是直截了当的事情,但我还没有完全能够找到一个好的解决方案。
在 MVC 中创建可重用内容的方法有很多,但它们各有利弊。例如,自定义 Html 帮助程序是一种常用方法,但它们需要编写的代码比您可能想要的要多得多。
您当然可以使用分部视图,只需将包含您要呈现的内容的模型传递给分部...但这也可能有点令人困惑。
我想您正在寻找的可能是 Razor Helpers。这些在此处有更详细的解释:
http://weblogs.asp.net/scottgu/asp-net-mvc-3-and-the-helper-syntax-within-razor
但是,基本结构如下所示:
@helper MyHelper(string content)
{
<div class="panel panel-default">
<div class="panel-body">
@Html.Raw(content)
</div>
</div>
}
然后你这样使用它:
@MyHelper("<img src="image.jpg" />")
你不必使用字符串,你可以使用结构化内容、模型等。你可以在里面使用其他帮助器。您可以按照本文后面的描述重新使用它们。
但是,您可能想要开始考虑将您的页面更多地以数据为中心。如果您使用 EditorTemplates 呈现您的数据,那么您将根据您的数据类型呈现控件,而不是呈现您的页面并尝试调整您的页面以包含您的数据。
您可以使用 "DynamicInvoke" 创建带有动态标记的 html 助手,例如:
public static IHtmlString CustomPanel(this HtmlHelper htmlHelper, Func<object, object> panelMarkup = null)
{
return CustomPanel(htmlHelper, (panelMarkup == null ? "" : panelMarkup.DynamicInvoke(htmlHelper.ViewContext).ToString()));
}
public static IHtmlString CustomPanel(this HtmlHelper htmlHelper, string content)
{
TagBuilder div = new TagBuilder("div");
div.AddCssClass("panel panel-default");
TagBuilder innerDiv = new TagBuilder("div");
innerDiv.AddCssClass("panel-body");
innerDiv.InnerHtml = content;
div.InnerHtml = innerDiv.ToString();
return new HtmlString(div.ToString());
}
然后你会像这样使用它:
@Html.CustomPanel(
@<text>
<div>My Custom Markup</div>
<span>More Stuff</span>
</text>
)
您的最终内容将如下所示:
<div class="panel panel-default">
<div class="panel-body">
<div>My Custom Markup</div>
<span>More Stuff</span>
</div>
</div>
你看到这个在一些第 3 方小部件库中经常使用(kendo-ui 是我所知道的主要的)