4

有没有人为 MVC 编写过任何HTMLHelper 类来帮助Yahoo 的用户界面库

例如,我编写了一个辅助方法来将“菜单模型”转换为支持Yahoo Menu Control所需的 HTML 标记。MVC 模式在这里工作得很好,因为很明显,如果我选择切换到不同的菜单实现,我可以只编写一个新的帮助程序而不接触模型。

此代码适用于我,但尚未经过全面测试,欢迎您使用它。

首先,我们需要菜单模型本身的简单数据结构。您可以使用正常的 MVC 约定将其添加到您的页面模型中。例如,我通过ViewData.Model.MainMenu.MenuOptions.

public class MenuItem

{
    public string Text { get; set; }
    public string Description { get; set; }
    public string RouteURL { get; set; }
    public bool SeparatorBefore { get; set; }

    public List<MenuItem> MenuItems { get; set; }
}

扩展方法。放入您的视图可访问的命名空间。

public static class YUIExtensions
    {
        public static string RenderMenu(this HtmlHelper html, string id, List<MenuItem> menuItems)
        {
            // <div id="mnuTopNav" class="yuimenubar yuimenubarnav">
            //    <div class="bd">
            //        <ul class="first-of-type">

            //            <li class="yuimenubaritem first-of-type"><a class="yuimenubaritemlabel" href="#store">Store</a></li>

            //            <li class="yuimenubaritem"><a class="yuimenubaritemlabel" href="#products">Products</a>

            //                <div id="communication" class="yuimenu">
            //                    <div class="bd">
            //                        <ul>
            //                            <li class="yuimenuitem"><a class="yuimenuitemlabel" href="http://360.yahoo.com">360&#176;</a></li>
            //                            <li class="yuimenuitem"><a class="yuimenuitemlabel" href="http://mobile.yahoo.com">Mobile</a></li>
            //                            <li class="yuimenuitem"><a class="yuimenuitemlabel" href="http://www.flickr.com">Flickr Photo Sharing</a></li>
            //                        </ul>
            //                    </div>
            //                </div>     
            //            </li>

            //        </ul>            
            //    </div>
            //</div>   

            int menuId = 0;
            HtmlGenericControl menuControl = CreateControl(html, id, 0, ref menuId, menuItems);

            // render to string
            StringWriter sw = new StringWriter();
            HtmlTextWriter tw = new HtmlTextWriter(sw);
            tw.Indent = 1;
            menuControl.RenderControl(tw);
            return sw.ToString();
        }

        private static HtmlGenericControl CreateControl(HtmlHelper html, string id, int level, ref int menuId, List<MenuItem> currentItems)
        {
            var menu = new HtmlGenericControl("div");
            menu.Attributes["class"] = (level == 0) ? "yuimenubar yuimenubarnav" : "yuimenu";
            menu.Attributes["id"] = id;

            var div_bd = new HtmlGenericControl("div");
            menu.Controls.Add(div_bd);
            div_bd.Attributes["class"] = "bd";

            HtmlGenericControl ul = null;

            int i = 0;
            foreach (var menuItem in currentItems)
            {
                if (ul == null || menuItem.SeparatorBefore)
                {
                    ul = new HtmlGenericControl("ul");
                    div_bd.Controls.Add(ul);

                    if (i == 0)
                    {
                        ul.Attributes["class"] = "first-of-type";
                    }
                }

                var menuItem_li = new HtmlGenericControl("li");
                menuItem_li.Attributes["class"] = (level == 0) ? "yuimenubaritem" : "yuimenuitem";
                if (i == 0)
                {
                    menuItem_li.Attributes["class"] += " first-of-type";
                }
                ul.Controls.Add(menuItem_li);

                var href = new HtmlGenericControl("a");
                href.Attributes["class"] = (level == 0) ? "yuimenubaritemlabel" : "yuimenuitemlabel";
                href.Attributes["href"] = menuItem.RouteURL;
                href.InnerHtml = menuItem.Text;
                menuItem_li.Controls.Add(href);

                if (menuItem.MenuItems != null && menuItem.MenuItems.Count > 0)
                {
                    menuItem_li.Controls.Add(CreateControl(html, id + "_" + (menuId++), level + 1, ref menuId, menuItem.MenuItems));
                }
                i++;
            }

            return menu;
        }
    }

将此代码粘贴到您要在视图中生成菜单的位置(我在母版页中有此代码):

<%= Html.RenderMenu("mnuTopNav", ViewData.Model.MainMenu.MenuOptions) %>

如果你很懒惰,或者不了解 YUI,你也需要这个<HEAD>

<!-- Combo-handled YUI CSS files: -->
<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/combo?2.6.0/build/menu/assets/skins/sam/menu.css">
<!-- Combo-handled YUI JS files: -->
<script type="text/javascript" src="http://yui.yahooapis.com/combo?2.6.0/build/yahoo-dom-event/yahoo-dom-event.js&2.6.0/build/container/container_core-min.js&2.6.0/build/menu/menu-min.js"></script>

这目前为顶部导航样式导航栏生成标记- 但可以轻松修改。

我希望其他人对其他一些控件也做同样的事情。

似乎是一个开源项目的好候选人——但我没有时间开始。

欢迎实施咨询!

4

2 回答 2

3

昨晚我对此进行了一些思考,想知道这里是否有更多机会使用 YUI 或您想要的任何其他 Javascript/HTML 小部件制作通用 HTMLHelpers。

例如,如果有一个 IMenu 接口和一个用于 ITextBox、ICheckBox、IRichTextEditor、ICarousel 等的接口,就像您的 MenuItem 类一样,那么您可以拥有每个接口的 YUI 实现,一个用于 JQuery,一个用于MooTools 或仅用于直接 HTML/CSS 的工具。

引发这种情况的部分原因是这样的文章的概括:http: //designingwebinterfaces.com/essential_controls正在将 Web 上的 UI 控件用于富 Web 应用程序。

这些接口将包含所有乍一看很明显的基本内容:Id、Name、Value、List、Style、OnChange、OnClick 等,以及不太明显的内容,如 ValidationRegex、HelpText 等。

这将使您拥有一个将模型对象或模型属性转换为 ITextBox 的层,而不必担心接口的哪个实现将实际处理它。如果出现更好/更快/更酷的新实现,您也可以轻松切换到新的实现。

如果您将诸如 ValidationRegex 之类的东西提供给准系统 HTML 实现并且它无法处理它,您将不得不处理会发生什么,但我认为这是一条值得思考的路径。我还认为,通过继承或重新实现它,将它与现有的 HTMLHelper 命名空间分开实现可能更有意义,但在提出解决方案的这种早期想法阶段,我经常犯错。

YUIAsp.NET 的东西很有趣,但比 ASP.NET MVC 和 Fubu MVC 最近的方向更面向 WebForms 和用户控件。

我对这个想法进行了一些修改,并且对这些可能性非常感兴趣。

于 2009-02-05T17:57:34.020 回答
2

西蒙,

我不确定这对 MVC 问题是否有帮助,但有一个很好的开源项目旨在简化在 .NET 中使用 YUI:

http://www.yuiasp.net/

菜单是它们包含的控件之一。

至少,如果您的工作为已经存在的东西增加了新的维度,那么这可能是一个您可以回馈的项目。

-埃里克

于 2009-01-26T06:23:48.147 回答