YUI 控件(雅虎用户界面)的 ASP.NET MVC HtmlHelper 扩展?

发布于 2024-07-12 19:58:06 字数 5820 浏览 4 评论 0原文

有没有人写过 HTMLHelper 类 的 MVC 有助于 Yahoo 的用户界面库

例如我编写了一个辅助方法,将“菜单模型”转换为支持 雅虎菜单控制。 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,则您在 中也需要此代码;

<!-- 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>

目前,这会生成 顶部导航样式导航栏 - 但它可以很容易地修改。

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

似乎是开源项目的良好候选者 - 但我没有时间开始。

欢迎实施建议!

Has anyone written any HTMLHelper classes for MVC that help with Yahoo's User Interface Library?

For instance I have written a helper method to convert a 'menu model' into the HTML markup needed to support the Yahoo Menu Control. The MVC pattern works well here because obviously if I chose to switch to a different menu implementation I can just write a new helper and not touch the model.

This code works for me but isn't fully tested and you're welcome to use it.

First we need a simple data structure for the menu model itself. You would add this to your page model with the normal MVC conventions. For instance I access a list of menu items from my view via 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; }
}

Extension method. Put in a namespace that is accessible to your view.

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°</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;
        }
    }

Stick this code where you want to generate the menu in your view (I have this in a master page):

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

If you're lazy, or don't know about YUI you'll need this too in your <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>

This currently generates markup for top nav style navigation bar - but it could be easily modified.

I was hoping somebody else was doing the same for some of the other controls.

Seems like a good candidate for an open source project - but I dont have time to start that.

Implementation advice welcomed!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

骄兵必败 2024-07-19 19:58:19

Simon,

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

http://www.yuiasp.net/

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

至少,如果您的工作为现有项目添加了新的维度,那么这可能是您可以回馈的项目。

-埃里克

Simon,

I'm not sure this is helpful with respect to the MVC question, but there is a good open-source project that aims to simplify working with YUI within .NET:

http://www.yuiasp.net/

Menu is one of the controls that they include.

At the very least, this may be a project you can contribute back to if your work adds a new dimension to what's already there.

-Eric

孤者何惧 2024-07-19 19:58:15

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

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

引发此问题的部分原因是以下文章的概括:http://designingwebinterfaces.com/essential_controls丰富的 Web 应用程序的 Web UI 控件。

这些界面将包含乍一看显而易见的所有基本内容:Id、Name、Value、List、Style、OnChange、OnClick 等,以及不太明显的内容,如 ValidationRegex、HelpText 等

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

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

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

我对这个想法做了一些修改,并对它的可能性非常感兴趣。

Last night I did some thinking about this and am wondering if there's even more opportunity here to make general purpose HTMLHelpers using YUI or whatever other Javascript/HTML widgets you want.

For instance, if there was an interface for IMenu and one for ITextBox, ICheckBox, IRichTextEditor, ICarousel, etc. much like your class for a MenuItem, then you could have a YUI implementation of each of those interfaces, one for JQuery, one for MooTools or one for just straight HTML/CSS.

Part of what sparked this is the generalization that articles like this: http://designingwebinterfaces.com/essential_controls are taking to UI controls on the web for rich web apps.

Those interfaces would contain all of the basic stuff that is obvious at first glance: Id, Name, Value, List, Style, OnChange, OnClick, etc. as well as less obvious stuff like ValidationRegex, HelpText, etc.

That would let you have a layer that converts a model object or model property into an ITextBox and not worry about which one of the implementations of the interface will actually be handling it. You could also easily switch to a new implementation if one came along that was better/faster/cooler.

You'd have to deal with what should happen if you give something like ValidationRegex to a barebones HTML implementation and it has no way to deal with it, but I think it's a path worth thinking about. I also think it might make more sense to implement this as separate from the existing HTMLHelper namespace by inheriting it or just reimplementing it, but I am often wrong at this kind of early idea stage of coming up with a solution.

The YUIAsp.NET stuff is interesting, but is more oriented to WebForms and user controls than the direction that ASP.NET MVC and even moreso with Fubu MVC recently are going.

I tinkered with this idea a little bit and am really intrigued with the possibilities.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文