如何在ASP.NET MVC中创建可重用的自定义HTML面板?

时间:2015-01-22 19:53:55

标签: asp.net-mvc partial-views

我正在尝试在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。当我输入特定参数时,这很有效。当需要输入大量标记时,我不认为这是实用的,因为它会变成难以阅读/维护。此外,由于html将作为字符串传递,我不确定这如何适用于剃刀标签?
  • 2部分视图。使用一个作为页眉,另一个作为页脚。这很有效,但对我来说只是感觉很草率。

我可以通过创建自定义控件在ASP.NET WebForms中执行此操作。看起来这在MVC中应该是直截了当的,但我还没有能够找到一个好的解决方案。

2 个答案:

答案 0 :(得分:2)

您可以使用&#34; DynamicInvoke&#34;使用动态标记创建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>

你看到这在一些第三方小部件库中经常使用(kendo-ui是我所知道的主要部分)

答案 1 :(得分:0)

有许多方法可以在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渲染数据,那么您将根据数据类型呈现控件,而不是渲染页面并尝试调整页面以包含数据。