【问题标题】:Problem in creating a ServerControl in ASP.NET , C#?在 ASP.NET、C# 中创建 ServerControl 时出现问题?
【发布时间】:2011-05-09 19:39:34
【问题描述】:

我正在开发 ServerControl(SuperFish 菜单)。
以下是我的代码。

菜单.cs

[AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
[AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
[ParseChildren(true, "MenuItems")]
[PersistChildren(true)]
[ToolboxData("<{0}:Menu runat=\"server\"></{0}:Menu>")]
public class Menu : WebControl, INamingContainer
{
    #region Fields

    List<MenuItem> _MenuItems;

    #endregion

    #region Properties

    public VerOrHor VerticalOrHorizontal { get; set; }

    public string Main_ul_CssClass { get; set; }

    [PersistenceMode(PersistenceMode.InnerDefaultProperty)]
    public animation AnimationItems { get; set; }

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    [PersistenceMode(PersistenceMode.InnerDefaultProperty)]
    public List<MenuItem> MenuItems
    {
        get
        {
            if (_MenuItems == null)
            {
                _MenuItems = new List<MenuItem>();
            }
            return _MenuItems;
        }
    }

    string _AnimationType
    {
        get
        {
            switch (this.AnimationItems.AnimationType)
            {
                case AnimationType.Opacity_Height:
                    return "animation:{opacity:'show',height:'show'}";
                case AnimationType.Opacity:
                    return "animation:{opacity:'show'}";
                case AnimationType.Height:
                    return "animation:{height:'show'}";
                default:
                    return "animation:{opacity:'show',height:'show'}";
            }
        }
    }

    string _AnimationSpeed
    {
        get
        {
            switch (this.AnimationItems.AnimationSpeed)
            {
                case AnimationSpeed.Fast:
                    return "speed:Fast";
                case AnimationSpeed.Normal:
                    return "speed:Normal";
                case AnimationSpeed.Slow:
                    return "speed:Slow";
                default:
                    return "speed:Fast";
            }
        }
    }

    #endregion

    #region Methods

    public override void RenderBeginTag(HtmlTextWriter writer)
    {

    }

    public override void RenderEndTag(HtmlTextWriter writer)
    {

    }

    protected override void AddAttributesToRender(HtmlTextWriter writer)
    {
        base.AddAttributesToRender(writer);
    }

    protected override void OnPreRender(EventArgs e)
    {
        base.OnPreRender(e);

        #region Adding Script & link Tags

        HtmlGenericControl jquery = new HtmlGenericControl("script");
        jquery.Attributes.Add("type", "text/javascript");
        jquery.Attributes.Add("src", Page.ClientScript.GetWebResourceUrl(typeof(Menu), "JQueryMenu.JavaScriptFiles.jquery_1_4_3.js"));
        jquery.EnableViewState = false;
        Page.Header.Controls.Add(jquery);

        HtmlGenericControl hoverIntent = new HtmlGenericControl("script");
        hoverIntent.Attributes.Add("type", "text/javascript");
        hoverIntent.Attributes.Add("src", Page.ClientScript.GetWebResourceUrl(typeof(Menu), "JQueryMenu.JavaScriptFiles.hoverIntent.js"));
        hoverIntent.EnableViewState = false;
        Page.Header.Controls.Add(hoverIntent);

        HtmlGenericControl jquery_bgiframe_min = new HtmlGenericControl("script");
        jquery_bgiframe_min.Attributes.Add("type", "text/javascript");
        jquery_bgiframe_min.Attributes.Add("src", Page.ClientScript.GetWebResourceUrl(typeof(Menu), "JQueryMenu.JavaScriptFiles.jquery_bgiframe_min.js"));
        jquery_bgiframe_min.EnableViewState = false;
        Page.Header.Controls.Add(jquery_bgiframe_min);

        HtmlGenericControl superfish = new HtmlGenericControl("script");
        superfish.Attributes.Add("type", "text/javascript");
        superfish.Attributes.Add("src", Page.ClientScript.GetWebResourceUrl(typeof(Menu), "JQueryMenu.JavaScriptFiles.superfish.js"));
        superfish.EnableViewState = false;
        Page.Header.Controls.Add(superfish);

        HtmlGenericControl supersubs = new HtmlGenericControl("script");
        supersubs.Attributes.Add("type", "text/javascript");
        supersubs.Attributes.Add("src", Page.ClientScript.GetWebResourceUrl(typeof(Menu), "JQueryMenu.JavaScriptFiles.supersubs.js"));
        supersubs.EnableViewState = false;
        Page.Header.Controls.Add(supersubs);

        HtmlGenericControl csslink = new HtmlGenericControl("link");
        csslink.Attributes.Add("href", Page.ClientScript.GetWebResourceUrl
            (typeof(Menu), "JQueryMenu.CSS.superfish.css"));
        csslink.ID = "NavigationMenu";
        csslink.Attributes.Add("type", "text/css");
        csslink.Attributes.Add("rel", "stylesheet");
        csslink.EnableViewState = false;
        Page.Header.Controls.Add(csslink);

        if (this.VerticalOrHorizontal == VerOrHor.Vertical)
        {
            HtmlGenericControl csslink01 = new HtmlGenericControl("link");
            csslink01.Attributes.Add("href", Page.ClientScript.GetWebResourceUrl
                (typeof(Menu), "JQueryMenu.CSS.superfish-vertical.css"));
            csslink01.Attributes.Add("type", "text/css");
            csslink01.Attributes.Add("rel", "stylesheet");
            csslink01.EnableViewState = false;
            Page.Header.Controls.Add(csslink01);
        }

        #endregion
    }

    protected override void RenderContents(HtmlTextWriter output)
    {
        output.Write(CreateMenuHtmlTags().ToString());
    }

    StringBuilder CreateMenuHtmlTags()
    {
        if (_MenuItems == null || _MenuItems.Count <= 0)
            throw new Exception("Please Fill the control with <MenuItem> tags");

        StringBuilder Html = new StringBuilder("");

        #region Add <Script>

        if (String.IsNullOrEmpty(Main_ul_CssClass))
            Html.Append("<script>$(document).ready(function() { $(\"ul.sf-menu\").superfish({pathLevels:    1,");
        else
            Html.Append("<script>$(document).ready(function() { $(\"ul." + Main_ul_CssClass + "\").superfish({ pathLevels:    1,");

        if (AnimationItems == null)
            Html.Append("delay:1000, animation:{opacity:'show',height:'show'}, speed:'normal', autoArrows:  true, dropShadows: true}); });</script>");
        else
        {
            Html.Append("delay:" + AnimationItems.Delay.Trim() + ",");
            Html.Append(_AnimationType + ",");
            Html.Append(_AnimationSpeed + ",");
            Html.Append("dropShadows:  " + AnimationItems.DropShadow.ToString() + ",");
            Html.Append(@"autoArrows:  false});});</script>");
        }

        #endregion

        if (String.IsNullOrEmpty(Main_ul_CssClass))
            Html.Append("<ul class=\"sf-menu sf-js-enabled sf-shadow\" id='sample-menu-1'>");
        else
            Html.Append("<ul class=\"" + Main_ul_CssClass + "\" id='sample-menu-1'>");

        foreach (MenuItem item in _MenuItems)
        {
            if (item.SubMenuItems != null || item.SubMenuItems.Count > 0)
            {
                if (!string.IsNullOrEmpty(item.li_CssClass))
                    Html.Append("<li class=\"" + item.li_CssClass + "\">");
                else
                    Html.Append("<li>");
                Html.Append("<a href=\"" + item.href + "\">" + item.Text.Trim() + "</a>");
                ParseSubMenuItems(ref Html, item);
                Html.Append("</li>");
            }
            else
                Html.Append("<li><a href=\"" + item.href + "\">" + item.Text.Trim() + "</a></li>");
        }
        Html.Append("</ul>");

        return Html;
    }

    void ParseSubMenuItems(ref StringBuilder Html, MenuItem menuItems)
    {
        if (menuItems == null || menuItems.SubMenuItems.Count == 0) return;

        Html.Append("<ul class=\"" + menuItems.ul_CssClass.Trim() + "\" style=\"display: none; visibility: hidden;\">");
        foreach (MenuItem item in menuItems.SubMenuItems)
        {
            if (item.SubMenuItems != null || item.SubMenuItems.Count > 0)
            {
                if (!string.IsNullOrEmpty(item.li_CssClass))
                    Html.Append("<li class=\"" + item.li_CssClass + "\">");
                else
                    Html.Append("<li>");
                Html.Append("<a href=\"" + item.href + "\">" + item.Text.Trim() + "</a>");
                ParseSubMenuItems(ref Html, item);
                Html.Append("</li>");
            }
            else
                Html.Append("<li><a href=\"" + item.href + "\">" + item.Text.Trim() + "</a></li>");
        }
        Html.Append("</ul>");
    }

    #endregion
}

public enum VerOrHor
{
    Vertical,
    Horizontal
}

public class MenuItemsCollectionEditor : CollectionEditor
{
    public MenuItemsCollectionEditor(Type type)
        : base(type)
    {
    }

    protected override bool CanSelectMultipleInstances()
    {
        return false;
    }

    protected override Type CreateCollectionItemType()
    {
        return typeof(MenuItem);
    }
}

MenuItem.cs

[PersistChildren(true)]
[ParseChildren(true, "SubMenuItems")]
public class MenuItem : Control, INamingContainer
{
    #region Fields

    List<MenuItem> _SubMenuItems;

    #endregion

    #region Properties

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    //[Editor(typeof(SubMenuItemsCollectionEditor), typeof(UITypeEditor))]
    [PersistenceMode(PersistenceMode.InnerDefaultProperty)]
    public List<MenuItem> SubMenuItems
    {
        get
        {
            if (_SubMenuItems == null)
            {
                _SubMenuItems = new List<MenuItem>();
            }
            return _SubMenuItems;
        }
    }

    [DefaultValue("MenuItem")]
    public string Text { get; set; }

    [DefaultValue("")]
    [Description("<ul /> css class")]
    public string ul_CssClass { get; set; }

    [DefaultValue("")]
    [Description("<li /> css class")]
    public string li_CssClass { get; set; }

    [DefaultValue("#")]
    [Description("<a /> href attribute")]
    public string href { get; set; }

    [TemplateContainer(typeof(MenuItem))]
    [PersistenceMode(PersistenceMode.InnerDefaultProperty)]
    public ITemplate Template { get; set; }

    #endregion
}

public class SubMenuItemsCollectionEditor : CollectionEditor
{
    public SubMenuItemsCollectionEditor(Type type)
        : base(type)
    {
    }

    protected override bool CanSelectMultipleInstances()
    {
        return false;
    }

    protected override Type CreateCollectionItemType()
    {
        return typeof(MenuItem);
    }
}

动画.cs

public class animation
{
    [DefaultValue("1000")]
    [NotifyParentProperty(true)]
    public string Delay { get; set; }

    [DefaultValue("Opacity_Height")]
    [NotifyParentProperty(true)]
    public AnimationType AnimationType { get; set; }

    [DefaultValue("fast")]
    [NotifyParentProperty(true)]
    public AnimationSpeed AnimationSpeed { get; set; }

    [DefaultValue("false")]
    [NotifyParentProperty(true)]
    public bool DropShadow { get; set; }
}

public enum AnimationType
{
    Opacity_Height,
    Opacity,
    Height
}

public enum AnimationSpeed
{
    Fast,
    Normal,
    Slow
}

它适用于以下代码(没有AnimationItems):

<MdsMenu:Menu ID="Menu1" runat="server">
    <MdsMenu:MenuItem Text="MenuItem 01"></MdsMenu:MenuItem>
    <MdsMenu:MenuItem Text="MenuItem 02"></MdsMenu:MenuItem>
    <MdsMenu:MenuItem Text="MenuItem 03" />
</MdsMenu:Menu>

但是当我像下面的代码一样添加AnimationItems标签时,我收到了异常:

异常:创建控件时出错 - Menu1Type“JQueryMenu.Menu”没有名为“MenuItem”的公共属性。

<MdsMenu:Menu ID="Menu1" runat="server">
    <AnimationItems AnimationSpeed="Fast" AnimationType="Opacity_Height" DropShadow="true" Delay="1000" />
    <MdsMenu:MenuItem Text="MenuItem 01"></MdsMenu:MenuItem>
    <MdsMenu:MenuItem Text="MenuItem 02"></MdsMenu:MenuItem>
    <MdsMenu:MenuItem Text="MenuItem 03" />
</MdsMenu:Menu>

【问题讨论】:

    标签: c# asp.net menu menuitem servercontrols


    【解决方案1】:

    您有两个用PersistenceMode.InnerDefaultProperty 装饰的属性,并且:

    只能指定一个属性 默认属性。

    我建议你用PersistenceMode.InnerProperty 来装饰你的AnimationItems 属性:

    [PersistenceMode(PersistenceMode.InnerProperty)]
    public animation AnimationItems
    {
        get;
        set;
    }
    

    编辑:以上还不够。我得到了代码,可以进行一些调整:

    首先,禁用子持久性并从[ParseChildren] 属性中删除defaultProperty 参数:

    [AspNetHostingPermission(SecurityAction.Demand,
        Level = AspNetHostingPermissionLevel.Minimal)]
    [AspNetHostingPermission(SecurityAction.InheritanceDemand,
        Level = AspNetHostingPermissionLevel.Minimal)]
    [ParseChildren(true)]
    [ToolboxData("<{0}:Menu runat=\"server\"></{0}:Menu>")]
    public class Menu : WebControl, INamingContainer
    {
    }
    

    然后,按照上面的建议,用PersistenceMode.InnerProperty 装饰AnimationItems 属性。对MenuItems 执行相同操作并删除其[DesignerSerializationVisibility] 属性:

    [PersistenceMode(PersistenceMode.InnerProperty)]
    public animation AnimationItems { get; set; }
    
    [PersistenceMode(PersistenceMode.InnerProperty)]
    public List<MenuItem> MenuItems
    {
    }
    

    最后,将&lt;MenuItems&gt; 元素添加到您的标记中:

    <MdsMenu:Menu ID="Menu1" runat="server">
        <AnimationItems AnimationSpeed="Fast" AnimationType="Opacity_Height"
            DropShadow="true" Delay="1000" />
        <MenuItems>
            <MdsMenu:MenuItem Text="MenuItem 01"></MdsMenu:MenuItem>
            <MdsMenu:MenuItem Text="MenuItem 02"></MdsMenu:MenuItem>
            <MdsMenu:MenuItem Text="MenuItem 03" />
        </MenuItems>
    </MdsMenu:Menu>
    

    【讨论】:

    • 我已经完成了,但我仍然收到错误!如果我删除 AnimationItems 效果很好!!!
    • @Mohammad,[DesignerSerializationVisibility][ParseChildren][PersistChildren][PersistenceMode] 之间可能存在冲突。有机会我会在虚拟机中尝试你的代码并回复你。
    • @Mohammad,为延迟道歉。请查看我的更新答案。
    • 能否请您指导我,我该如何渲染&lt;MdsMenu:Menu ID="Menu1" runat="server"&gt; &lt;AnimationItems AnimationSpeed="Fast" AnimationType="Opacity_Height" DropShadow="true" Delay="1000" /&gt; &lt;MenuItems&gt; &lt;MdsMenu:MenuItem Text="MenuItem 01"&gt;&lt;/MdsMenu:MenuItem&gt; &lt;MdsMenu:MenuItem Text="MenuItem 02"&gt;&lt;/MdsMenu:MenuItem&gt; &lt;MdsMenu:MenuItem Text="MenuItem 03" /&gt; &lt;/MenuItems&gt; &lt;/MdsMenu:Menu&gt;
    • @Mohammad,这是一个相当广泛的问题,所以我建议您将其作为另一个 StackOverflow 问题以及您当前的代码发布,以及有关您期望的结果的更多信息(例如澄清render) ,可能还有一个链接返回到这个问题,这样人们就可以获得更多的背景信息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-25
    • 1970-01-01
    相关资源
    最近更新 更多