【问题标题】:Method to encapsulate reusable view sections (i.e. tiles, portlets) with arbitrary content?用任意内容封装可重用视图部分(即磁贴、portlet)的方法?
【发布时间】:2012-10-23 20:17:06
【问题描述】:

我仍然对 MVC 感兴趣,并且在一个使用大量“图块”(您知道,通常的“带有标准化标题和一些内容的矩形部分”模式)用于视觉显示的网站上工作。没有什么花哨的,只是一种将内容放入框中以便于布局和导航的方法。目前,“瓷砖”(我的术语)是这样构建的:

<div class="tile">
    <div class="tile-header">
        <h2>Title</h2>
    </div>
    <div class="tile-body">
        (arbitrary content)
    </div>
</div>

注意:“任意内容”是指任何内容,无论是静态的还是动态的,所以不一定可以插入变量并传递给帮助程序,我需要更多的灵活性。 p>

我的问题是,封装此模式并使其更容易/更具表现力地从代码调用的最佳方法是什么?我知道部分视图,但我如何将任意正文内容传递给部分视图? (这可能只是我对 MVC 展示的有限了解)

我尝试像这样构建 Razor 助手:

@Tile.Begin("Title")
    (arbitrary content)
@Tile.End()

但是 Razor 窒息,因为我不能包含“tile-body”关闭 div。 (如果我这样做了,我必须将正文内容作为字符串变量传递,这并不总是可行的)

我可以看到这样的东西:

@using (Tile.Begin("Title")) {
    (arbitrary content)
}

这对我来说似乎是最优雅的,虽然不像 @Tile.Begin() 和 @Tile.End() 调用那么容易扫描。据我了解,我必须创建一个类并实现 IDisposable,但是当我尝试从帮助类返回一串原始 HTML 标记时,它只是将编码的标记语法写入屏幕,所以我假设我会遇到同样的问题?

感谢您的任何建议。 :)

【问题讨论】:

  • 您说的是固定(静态)图块吗?还是动态(数据驱动)图块?也就是说,您是想在 .cshtml 文件中定义图块,还是想在代码中构建时间?
  • 其实两者都有。例如,现在我正在构建一个本质上是列表集合的屏幕,每个列表迭代一个模型集合。这些模型附加到传递给视图的视图模型。所以本质上,视图是获取每个模型集合并为它构建一个带有链接的图块。这个我可以用一个帮手包起来,当然。但是另一个页面具有与静态内容相同的平铺格式,我不能将其作为变量传入。我宁愿有 一个 中心位置来维护瓷砖的布局,因为那是干燥的,但我只是不知道如何到达那里。谢谢。
  • 实际上不,我也不能轻易地将这个包装成一个助手,因为并非所有模型都有相同的方法调用。我想我可以在每个模型上重载 ToString() ,除非那是反模式?

标签: asp.net-mvc asp.net-mvc-3


【解决方案1】:

好吧,我建议使用 Display/EditorTemplates 来生成动态图块。您甚至可以将它们与 html 助手(而不是 razor 助手)结合使用。

您对自定义 html 帮助程序的问题是您没有正确执行它。您必须使用 HtmlHelper 对象。正确的做法是这样的:

public static class TileExtension {

    public static TileHelper Tile(this HtmlHelper helper, string title) {
        helper.ViewContext.Writer.Write(
            "<div class=\"tile\"><div class=\"tile-header\"><h2>" + title + "</h2></div>"
            + "<div class=\"tile-body\">"
        );
        return new TileHelper(helper);
    }

    private class TileHelper : IDisposable {
        private HtmlHelper _helper;
        public TileHelper(HtmlHelper helper) { _helper = helper; }
        public void Dispose() {
           _helper.ViewContext.Writer.Write("</div></div>");
        }
    }
}

然后你会像@using(Html.Tile("Title")) { // your content }一样使用它

请务必密切注意静态关键字,以及参数中this 关键字的使用。这些是使扩展工作所必需的。

此外,您应该将创建此类的命名空间添加到 web.config 的 pages/namespaces 元素中:

<pages>
    <namespaces>
        <add namespace="My.Name.Space" />
    </namespaces>
<pages>

【讨论】:

  • 好的,谢谢,我不知道 ViewContext.Writer 对象,它会派上用场。不幸的是,当我尝试实现上述代码时,没有显示 Html 帮助器对象的 Tile() 方法。我所做的是在 App_Code 文件夹(我的 cshtml 帮助文件所在的位置)中创建一个 Tile.cs 文件。我确实包含了第一个辅助扩展参数,并进行了完全重建,甚至在视图顶部做了一个@using ProjectName.App_Code;,但它仍然没有捡起它。所以我一定错过了一些简单的东西,但是在哪里呢?另外,您将如何实现您提到的 DisplayTemplates?再次感谢。
  • @Dave - 抱歉,不知道我之前在想什么。尝试更新版本。
  • 好吧,对不起,我永远无法让它工作。我什至在 web.config 文件中添加了对 razors 元素的命名空间引用。如果我在视图中引用命名空间(@using Project.Views.Helpers),那么我可以看到该类,但它根本不会显示为 @Html.Tile()。但是因为我至少可以获得一个静态类,所以我将使用 Tile.Begin()... Tile.End() 语法。我确定我缺少一些 MVC 魔力,但我稍后会弄清楚。标记为已回答,因为它为我指明了正确的方向。感谢您的帮助。
  • @Dave - 您必须确保类和 Tile 方法以及 Tile() 方法参数中 HtmlHelper 之前的 this 都具有静态属性。然后你需要将你的助手的命名空间添加到 Web.config pages/namespaces 元素&lt;add namespace="Your.Name.Space" /&gt;
  • 噢!我在构建我的时候放弃了this 关键字——就这样!谢谢!现在我可以对 CSS 网格做同样的事情。说真的,感谢您抽出宝贵的时间,我很感激。
猜你喜欢
  • 2014-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-01
  • 2012-03-12
  • 1970-01-01
相关资源
最近更新 更多