Пользовательский WebControl указан в списке триггеров asyncpostback в UpdatePanel, но при нажатии все равно вызывает полное синхронное обновление страницы - PullRequest
1 голос
/ 17 ноября 2011

Я пытаюсь построить UserControl;визуально настраиваемый LinkButton.Все было хорошо, пока UpdatePanels не вошли в микс: мой пользовательский контроль FancyButton вызывает обновление страницы.Для сравнения я также использую традиционный LinkButton, который работает по назначению.

//Doesn't work: Causes whole page to refresh/reload.
<as:FancyButton ID="fbUpload"
    runat="server" Text="FancyButton"/>

//Works as intended: Causes ajax refresh of Update Panel.
<asp:LinkButton ID="btnUpload" runat="server" Text="LinkButton" />

Вот мой код updatePanel:

<asp:UpdatePanel ID="upNewUpdatePanel" UpdateMode="Always" ChildrenAsTriggers="true"
    runat="server">
    <Triggers>
        <asp:AsyncPostBackTrigger ControlID="fbUpload" EventName="Click" />
        <asp:AsyncPostBackTrigger ControlID="btnUpload" EventName="Click" />
    </Triggers>
    <ContentTemplate>
        <asp:PlaceHolder ID="detailPlaceHolder" runat="server" />
    </ContentTemplate>
</asp:UpdatePanel>

А вот код для FancyButton UserControl: Я почти уверен, что проблема здесь:

using System;
using System.Web.UI.WebControls;
using System.Web.UI;


namespace Jake
{
    public class FancyButton : WebControl, INamingContainer
    {
        private LinkButton _btn;


        public string Text
        {
            get
            {
                EnsureChildControls();
                return _btn.Text;
            }
            set
            {
                EnsureChildControls();
                _btn.Text = value;
            }
        }

        public string OnClientClick
        {
            get 
            {
                EnsureChildControls();
                return _btn.OnClientClick;
            }
            set
            {
                EnsureChildControls();
                _btn.OnClientClick = value;
            }
        }

        public delegate void ClickEventHandler(object sender, EventArgs e);
        public event ClickEventHandler Click = delegate { };

        protected void _btn_Click(object sender, EventArgs e)
        {
            Click(this, e);
        }



        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            EnsureChildControls();
        }

        protected override void CreateChildControls()
        {
            base.CreateChildControls();

            _btn = new LinkButton { ID = "btn" };
            Controls.Add(_btn);

        }

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

        protected override void Render(HtmlTextWriter writer)
        {   
            //<a class="btn {Color} btn-{Color}{CssClass?}{hasImage?}">
            writer.AddAttribute(HtmlTextWriterAttribute.Class, "fancyButton");
            _btn.RenderBeginTag(writer);

            if (Text != null)
            {
                writer.Write(Text);
            }

            _btn.RenderEndTag(writer);

        }
    }
}

TL; DR: обычная кнопка связи работает как асинхронный триггер;мой кастом, кнопки UserControl нет.Что я делаю не так?


Решение из принятого ответа

Унаследовав LinkButton вместо WebControl, обновление панели Async работаеткак предполагалось.Кроме того, все эти надоедливые override методы стали ненужными.

namespace Jake
{
    public class FancyButton : LinkButton
    {
        public string Color
        {
            get
            {
                if ( ViewState["Color"] != null && ((string)ViewState["Color"]).Length > 0)
                {
                    return ((string)ViewState["Color"]).ToLower();
                }
                else return "white";
            }
            set { ViewState["Color"] = value; }
        }
        public string Icon
        {
            get { return (string)ViewState["Icon"]; }
            set { ViewState["Icon"] = value; }
        }
        protected override void Render(HtmlTextWriter writer)
        {
            //<a class="btn {Color} btn-{Color}{CssClass?}{hasImage?}">
            writer.AddAttribute(HtmlTextWriterAttribute.Class, string.Format("fancyButton {0}{1}{2}",
                this.Color,
                CssClass.Length > 0 ? " " + CssClass : string.Empty,
                Icon != null && Icon.Length > 0 ? " hasIcon" : String.Empty));
            this.RenderBeginTag(writer);

            // <span>
            writer.RenderBeginTag(HtmlTextWriterTag.Span);

            // <div class="icon {IconClass}"></div>
            if (Icon != null)
            {
                writer.AddAttribute(HtmlTextWriterAttribute.Class, string.Format("icon {0}{1}",
                    Icon,
                    Text != null ? " btnIconPadding" : ""));
                writer.RenderBeginTag(HtmlTextWriterTag.Div);
                writer.RenderEndTag();
            }
            if (Text != null)
            {
                writer.Write(Text);
            }

            // </span>
            writer.RenderEndTag();
            this.RenderEndTag(writer);

        }
    }
}

1 Ответ

1 голос
/ 18 ноября 2011

Не уверен на 100% в этом, но я предполагаю, что проблема в том, что кнопка, вызывающая обратную передачу, является частной изнутри вашего UserControl, который вы не можете так легко добавить к своим триггерам.

Самый чистый обходной путь, который я могу придумать, - это создать класс, который наследуется от LinkButton для настраиваемого элемента управления, а не UserControl. Недостаток: нет визуального дизайнера или страницы с разметкой.

Быстрый Google по этому вопросу косвенно привел меня к Microsoft Connect: https://connect.microsoft.com/VisualStudio/feedback/details/524827/dynamicdataentities-site-linkbutton-in-updatepanel#details

(не беспокойтесь о том, что он ссылается на форумы ASP.NET, если только вам не нравится биться головой о стену)

...