Home All Groups Group Topic Archive Search About

WebControl Click Event Not Firing

Author
5 Jan 2006 6:20 PM
Demetri
I have created a web control that can be rendered as either a linkbutton or a
button. It is a ConfirmButton control that allows a developer to force a user
to confirm if they intended to click it such as when they do a delete.

Everything is great. By and large it will be used in my repeater controls
using the command event when the user clicks on it and so that event is
working great.

My issue is the Click event. When the control is either in a repeater or by
itself on a page the click event does not fire. It never even gets raised by
the ConfirmButton control, never mind the listener (ie. page container).

Does anyone have a clue as to why the RaisePostBackEvent never fires? That
is my ultimate question here.

HTML output:

<input type="submit" name="Confirmbutton1" value="Go" id="Confirmbutton1"
onclick="return __doConfirm();__doPostBack('MyPage:Confirmbutton1','')" />

Page using the control event wiring:

        private void InitializeComponent()
        {
            this.Confirmbutton1.Click += new
System.EventHandler(this.Confirmbutton1_Click);
            this.Load += new System.EventHandler(this.Page_Load);

        }


        private void Confirmbutton1_Click(object sender, System.EventArgs e)
        {
            Response.Write("Click event fired!");
        }

Server Control Code:

using System;
using System.Text;
using System.Drawing;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.Web.UI.HtmlControls;
using System.Collections;

namespace WS.Ops.Web.CustomControls
{
    /// <summary>
    /// Button that provides a client-side confirmation prompt. It can be
either a Button or LinkButton.
    /// </summary>
    [DefaultProperty("Text"),
    ToolboxData("<{0}:ConfirmButton1 runat=server></{0}:ConfirmButton1>"),
    Description("Button that provides a client-side confirmation prompt. It can
be either a Button or LinkButton.")]
    public class ConfirmButton : System.Web.UI.WebControls.WebControl,
IPostBackEventHandler
    {
        //the confirm button render types
        public enum RenderTypes
        {
            LinkButton,
            Button
        };

        #region Fields
        private RenderTypes renderType = RenderTypes.LinkButton;
        private WebControl controlToRender;       
        private const string CONFIRMSCRIPTKEY = "ConfirmScript";
        private const string CONFIRMFUNCTIONNAME = "__doConfirm";
        private string confirmationText = "Are you sure you want to continue?";
        private string text = string.Empty;
        private string navigateUrl = string.Empty;
        private string commandArgument = string.Empty;
        private string commandName = string.Empty;
        private bool enableConfirmation = true;
        private bool causesValidation = true;
        private static readonly object EventCommand;
        #endregion

        #region Overrides
        protected override void CreateChildControls()
        {   
            base.CreateChildControls();

            switch (RenderType)
            {
                default:  // default is hyperlink
                case RenderTypes.LinkButton:

                    LinkButton link = new LinkButton();
                    link.TabIndex = -1;
                    link.Text = this.Text;                     link.Attributes.Add("href",Page.GetPostBackClientHyperlink(this,string.Empty));
                    link.Click += new EventHandler(this.OnClick);
                    link.Command += new CommandEventHandler(this.OnCommand);

                    if(EnableConfirmation)
                        link.Attributes.Add("onclick","return " + CONFIRMFUNCTIONNAME + "();");

                    controlToRender = link;

                    break;
                case RenderTypes.Button:

                    Button button = new Button();
                    button.Text = this.Text;
                    button.Click += new EventHandler(this.OnClick);
                    button.Command += new CommandEventHandler(this.OnCommand);

                    if(EnableConfirmation)
                        button.Attributes.Add("onclick","return " + CONFIRMFUNCTIONNAME +
"();" + Page.GetPostBackEventReference(this,string.Empty));

                    controlToRender = button;

                    break;
            }

            //Copy control style attributes applied to this control
            //to the control that will render
            IEnumerator keys = this.Style.Keys.GetEnumerator();
            while (keys.MoveNext())
            {
                string key = (string)keys.Current;
                controlToRender.Style.Add(key, this.Style[key]);
            }           

            //copy attributes applied to this control
            //to the control that will render
            IEnumerator attribKeys = this.Attributes.Keys.GetEnumerator();
            while (attribKeys.MoveNext())
            {
                string key = (string)attribKeys.Current;
                controlToRender.Attributes.Add(key, this.Attributes[key]);
            }

            if (this.CssClass != null && this.CssClass != string.Empty)
            {
                controlToRender.CssClass += " " + this.CssClass;
            }

            controlToRender.Enabled = this.Enabled;

            controlToRender.ID = this.ID;
        }

        protected override void Render(HtmlTextWriter output)
        {
            EnsureChildControls(); //make sure child controls are created

            //don't render this control, just the control chosen via
            //the RenderType property
            controlToRender.RenderControl(output);

        }

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

            //if enable confirmation then attach the
            //confirm script to the page
            if(EnableConfirmation)
            {
                RegisterConfirmationScript();
            }
        }

        #endregion

        #region Methods
        private void RegisterConfirmationScript()
        {
            //only add the script to the page
            //if it has not been added already
            if(!Page.IsClientScriptBlockRegistered(CONFIRMSCRIPTKEY))
            {                 Page.RegisterClientScriptBlock(CONFIRMSCRIPTKEY,CreateJavaScriptFunction());
            }           
        }

        private string CreateJavaScriptFunction()
        {
            //build script string, the script is formatted for
            //readability in view source
            StringBuilder sb = new StringBuilder();
            sb.Append("<script language=\"javascript\">" + Environment.NewLine);
            sb.Append("\tfunction " + CONFIRMFUNCTIONNAME + "(){" +
Environment.NewLine);
            sb.Append("\t\tvar agree = confirm(\"" + ConfirmationText + "\");" +
Environment.NewLine + Environment.NewLine);
            sb.Append("\t\tif(agree){" + Environment.NewLine);
            sb.Append("\t\t\treturn true;" + Environment.NewLine);
            sb.Append("\t\t}" + Environment.NewLine + "else{" + Environment.NewLine);
            sb.Append("\t\t\treturn false;" + Environment.NewLine);
            sb.Append("\t\t}" + Environment.NewLine);
            sb.Append("\t}" + Environment.NewLine);
            sb.Append("</script>" + Environment.NewLine);

            return sb.ToString();       
        }

        protected virtual void OnClick(object sender, EventArgs e)
        {
            if(Click != null)
                Click(this,e);
        }

        protected virtual void OnCommand(object sender,CommandEventArgs e)
        {
            CommandEventHandler handler =
(CommandEventHandler)base.Events[ConfirmButton.EventCommand];

            if(handler != null)
                handler(this,e);

            base.RaiseBubbleEvent(this,e);
        }
        #endregion

        #region Properties
        /// <summary>
        /// Gets or sets the text for the control.
        /// </summary>
        [Bindable(true),
        Category("Appearance"),
        DefaultValue(""),Description("Gets or sets the text for the control")]
        public string Text
        {
            get
            {
                return text;
            }

            set
            {
                text = value;
            }
        }

        /// <summary>
        /// Gets or sets the text for the confirmation message.
        /// </summary>
        [Bindable(true),
        Category("Appearance"),
        DefaultValue("Are you sure you want to continue?"),Description("Gets or
sets the text for the confirmation message.")]
        public string ConfirmationText
        {
            get
            {
                return confirmationText;
            }

            set
            {
                confirmationText = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether client-side confirmation is
enabled.
        /// </summary>
        [Bindable(true),
        Category("Appearance"),
        DefaultValue(true),Description("Gets or sets a value indicating whether
client-side confirmation is enabled.")]
        public bool EnableConfirmation
        {
            get
            {
                return enableConfirmation;
            }

            set
            {
                enableConfirmation = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating what type of button to render.
        /// </summary>
        [Bindable(true),
        Category("Appearance"),
        Description("Gets or sets a value indicating what type of button to
render.")]
        public RenderTypes RenderType
        {
            get
            {
                return renderType;
            }

            set
            {
                renderType = value;
            }
        }

        /// <summary>
        /// Gets or sets the url for the LinkButton RenderType.
        /// </summary>
        [Bindable(true),
        Category("Navigation"),
        DefaultValue(""),Description("Gets or sets the url for the LinkButton
RenderType.")]
        public string NavigateUrl
        {
            get
            {
                return navigateUrl;
            }

            set
            {
                navigateUrl = value;
            }
        }

        /// <summary>
        /// Gets or sets the command name associated with the ConfirmButton
control.
        /// </summary>
        [Category("Behavior"),
        Description("Gets or sets the command name associated with the
ConfirmButton control."),
        DefaultValue("")]
        public string CommandName
        {
            get
            {
                return commandName;
            }

            set
            {
                commandName = value;
            }
        }

        /// <summary>
        /// Gets or sets an optional argument passed to the Command event handler
along with the associated CommandName property.
        /// </summary>
        [Bindable(true),
        Category("Behavior"),
        Description("Gets or sets an optional argument passed to the Command event
handler along with the associated CommandName property."),
        DefaultValue("")]
        public string CommandArgument
        {
            get
            {
                return commandArgument;
            }

            set
            {
                commandArgument = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether validation is performed when
the ConfirmButton control is clicked.
        /// </summary>
        [Bindable(false),
        Category("Behavior"),
        Description("Gets or sets a value indicating whether validation is
performed when the ConfirmButton control is clicked."),
        DefaultValue(true)]
        public bool CausesValidation
        {
            get
            {
                return causesValidation;
            }

            set
            {
                causesValidation = value;
            }
        }
        #endregion

        #region Events
        /// <summary>
        /// Occurs when ConfirmButton control is clicked.
        /// </summary>
        public event EventHandler Click;

        /// <summary>
        /// Occurs when the ConfirmButton control is clicked.
        /// </summary>
        public event CommandEventHandler Command
        {
            add
            {
                base.Events.AddHandler(ConfirmButton.EventCommand,value);
            }
            remove
            {
                base.Events.RemoveHandler(ConfirmButton.EventCommand,value);
            }
        }
        #endregion

        #region IPostBackEventHandler Members

        /// <summary>
        /// Notifies the server control that caused the postback that it should
handle an incoming post back event.
        /// </summary>
        /// <param name="eventArgument">The post-back argument.</param>
        public void RaisePostBackEvent(string eventArgument)
        {
            this.OnClick(this, new System.EventArgs());
            this.OnCommand(this,new
CommandEventArgs(this.CommandName,this.CommandArgument));
        }

        #endregion

    }
}

--
-Demetri

Author
6 Jan 2006 10:01 AM
Teemu Keiski
As it has child controls dealing with postback, your control is a composite
control and needs also implement  INamingContainer interface so that the
postback data is routed correctly.

--
Teemu Keiski
ASP.NET MVP, AspInsider
Finland, EU
http://blogs.aspadvice.com/joteke

Show quoteHide quote
"Demetri" <Deme***@discussions.microsoft.com> wrote in message
news:CCA12D7E-01B9-44B1-BDED-C993798C201B@microsoft.com...
>I have created a web control that can be rendered as either a linkbutton or
>a
> button. It is a ConfirmButton control that allows a developer to force a
> user
> to confirm if they intended to click it such as when they do a delete.
>
> Everything is great. By and large it will be used in my repeater controls
> using the command event when the user clicks on it and so that event is
> working great.
>
> My issue is the Click event. When the control is either in a repeater or
> by
> itself on a page the click event does not fire. It never even gets raised
> by
> the ConfirmButton control, never mind the listener (ie. page container).
>
> Does anyone have a clue as to why the RaisePostBackEvent never fires? That
> is my ultimate question here.
>
> HTML output:
>
> <input type="submit" name="Confirmbutton1" value="Go" id="Confirmbutton1"
> onclick="return __doConfirm();__doPostBack('MyPage:Confirmbutton1','')" />
>
> Page using the control event wiring:
>
> private void InitializeComponent()
> {
> this.Confirmbutton1.Click += new
> System.EventHandler(this.Confirmbutton1_Click);
> this.Load += new System.EventHandler(this.Page_Load);
>
> }
>
>
> private void Confirmbutton1_Click(object sender, System.EventArgs e)
> {
> Response.Write("Click event fired!");
> }
>
> Server Control Code:
>
> using System;
> using System.Text;
> using System.Drawing;
> using System.Web.UI;
> using System.Web.UI.WebControls;
> using System.ComponentModel;
> using System.Web.UI.HtmlControls;
> using System.Collections;
>
> namespace WS.Ops.Web.CustomControls
> {
> /// <summary>
> /// Button that provides a client-side confirmation prompt. It can be
> either a Button or LinkButton.
> /// </summary>
> [DefaultProperty("Text"),
> ToolboxData("<{0}:ConfirmButton1 runat=server></{0}:ConfirmButton1>"),
> Description("Button that provides a client-side confirmation prompt. It
> can
> be either a Button or LinkButton.")]
> public class ConfirmButton : System.Web.UI.WebControls.WebControl,
> IPostBackEventHandler
> {
> //the confirm button render types
> public enum RenderTypes
> {
> LinkButton,
> Button
> };
>
> #region Fields
> private RenderTypes renderType = RenderTypes.LinkButton;
> private WebControl controlToRender;
> private const string CONFIRMSCRIPTKEY = "ConfirmScript";
> private const string CONFIRMFUNCTIONNAME = "__doConfirm";
> private string confirmationText = "Are you sure you want to continue?";
> private string text = string.Empty;
> private string navigateUrl = string.Empty;
> private string commandArgument = string.Empty;
> private string commandName = string.Empty;
> private bool enableConfirmation = true;
> private bool causesValidation = true;
> private static readonly object EventCommand;
> #endregion
>
> #region Overrides
> protected override void CreateChildControls()
> {
> base.CreateChildControls();
>
> switch (RenderType)
> {
> default:  // default is hyperlink
> case RenderTypes.LinkButton:
>
> LinkButton link = new LinkButton();
> link.TabIndex = -1;
> link.Text = this.Text;
> link.Attributes.Add("href",Page.GetPostBackClientHyperlink(this,string.Empty));
> link.Click += new EventHandler(this.OnClick);
> link.Command += new CommandEventHandler(this.OnCommand);
>
> if(EnableConfirmation)
> link.Attributes.Add("onclick","return " + CONFIRMFUNCTIONNAME + "();");
>
> controlToRender = link;
>
> break;
>  case RenderTypes.Button:
>
> Button button = new Button();
> button.Text = this.Text;
> button.Click += new EventHandler(this.OnClick);
> button.Command += new CommandEventHandler(this.OnCommand);
>
> if(EnableConfirmation)
> button.Attributes.Add("onclick","return " + CONFIRMFUNCTIONNAME +
> "();" + Page.GetPostBackEventReference(this,string.Empty));
>
> controlToRender = button;
>
> break;
> }
>
> //Copy control style attributes applied to this control
> //to the control that will render
> IEnumerator keys = this.Style.Keys.GetEnumerator();
> while (keys.MoveNext())
> {
> string key = (string)keys.Current;
> controlToRender.Style.Add(key, this.Style[key]);
> }
>
> //copy attributes applied to this control
> //to the control that will render
> IEnumerator attribKeys = this.Attributes.Keys.GetEnumerator();
> while (attribKeys.MoveNext())
> {
> string key = (string)attribKeys.Current;
> controlToRender.Attributes.Add(key, this.Attributes[key]);
> }
>
> if (this.CssClass != null && this.CssClass != string.Empty)
> {
> controlToRender.CssClass += " " + this.CssClass;
> }
>
> controlToRender.Enabled = this.Enabled;
>
> controlToRender.ID = this.ID;
> }
>
> protected override void Render(HtmlTextWriter output)
> {
> EnsureChildControls(); //make sure child controls are created
>
> //don't render this control, just the control chosen via
> //the RenderType property
> controlToRender.RenderControl(output);
>
> }
>
> protected override void OnPreRender(EventArgs e)
> {
> base.OnPreRender (e);
>
> //if enable confirmation then attach the
> //confirm script to the page
> if(EnableConfirmation)
> {
> RegisterConfirmationScript();
> }
> }
>
> #endregion
>
> #region Methods
> private void RegisterConfirmationScript()
> {
> //only add the script to the page
> //if it has not been added already
> if(!Page.IsClientScriptBlockRegistered(CONFIRMSCRIPTKEY))
> {
> Page.RegisterClientScriptBlock(CONFIRMSCRIPTKEY,CreateJavaScriptFunction());
> }
> }
>
> private string CreateJavaScriptFunction()
> {
> //build script string, the script is formatted for
> //readability in view source
> StringBuilder sb = new StringBuilder();
> sb.Append("<script language=\"javascript\">" + Environment.NewLine);
> sb.Append("\tfunction " + CONFIRMFUNCTIONNAME + "(){" +
> Environment.NewLine);
> sb.Append("\t\tvar agree = confirm(\"" + ConfirmationText + "\");" +
> Environment.NewLine + Environment.NewLine);
> sb.Append("\t\tif(agree){" + Environment.NewLine);
> sb.Append("\t\t\treturn true;" + Environment.NewLine);
> sb.Append("\t\t}" + Environment.NewLine + "else{" + Environment.NewLine);
> sb.Append("\t\t\treturn false;" + Environment.NewLine);
> sb.Append("\t\t}" + Environment.NewLine);
> sb.Append("\t}" + Environment.NewLine);
> sb.Append("</script>" + Environment.NewLine);
>
> return sb.ToString();
> }
>
> protected virtual void OnClick(object sender, EventArgs e)
> {
> if(Click != null)
> Click(this,e);
> }
>
> protected virtual void OnCommand(object sender,CommandEventArgs e)
> {
> CommandEventHandler handler =
> (CommandEventHandler)base.Events[ConfirmButton.EventCommand];
>
> if(handler != null)
> handler(this,e);
>
> base.RaiseBubbleEvent(this,e);
> }
> #endregion
>
> #region Properties
> /// <summary>
> /// Gets or sets the text for the control.
> /// </summary>
> [Bindable(true),
> Category("Appearance"),
> DefaultValue(""),Description("Gets or sets the text for the control")]
> public string Text
> {
> get
> {
> return text;
> }
>
> set
> {
> text = value;
> }
> }
>
> /// <summary>
> /// Gets or sets the text for the confirmation message.
> /// </summary>
> [Bindable(true),
> Category("Appearance"),
> DefaultValue("Are you sure you want to continue?"),Description("Gets or
> sets the text for the confirmation message.")]
> public string ConfirmationText
> {
> get
> {
> return confirmationText;
> }
>
> set
> {
> confirmationText = value;
> }
> }
>
> /// <summary>
> /// Gets or sets a value indicating whether client-side confirmation is
> enabled.
> /// </summary>
> [Bindable(true),
> Category("Appearance"),
> DefaultValue(true),Description("Gets or sets a value indicating whether
> client-side confirmation is enabled.")]
> public bool EnableConfirmation
> {
> get
> {
> return enableConfirmation;
> }
>
> set
> {
> enableConfirmation = value;
> }
> }
>
> /// <summary>
> /// Gets or sets a value indicating what type of button to render.
> /// </summary>
> [Bindable(true),
> Category("Appearance"),
> Description("Gets or sets a value indicating what type of button to
> render.")]
> public RenderTypes RenderType
> {
> get
> {
> return renderType;
> }
>
> set
> {
> renderType = value;
> }
> }
>
> /// <summary>
> /// Gets or sets the url for the LinkButton RenderType.
> /// </summary>
> [Bindable(true),
> Category("Navigation"),
> DefaultValue(""),Description("Gets or sets the url for the LinkButton
> RenderType.")]
> public string NavigateUrl
> {
> get
> {
> return navigateUrl;
> }
>
> set
> {
> navigateUrl = value;
> }
> }
>
> /// <summary>
> /// Gets or sets the command name associated with the ConfirmButton
> control.
> /// </summary>
> [Category("Behavior"),
> Description("Gets or sets the command name associated with the
> ConfirmButton control."),
> DefaultValue("")]
> public string CommandName
> {
> get
> {
> return commandName;
> }
>
> set
> {
> commandName = value;
> }
> }
>
> /// <summary>
> /// Gets or sets an optional argument passed to the Command event handler
> along with the associated CommandName property.
> /// </summary>
> [Bindable(true),
> Category("Behavior"),
> Description("Gets or sets an optional argument passed to the Command event
> handler along with the associated CommandName property."),
> DefaultValue("")]
> public string CommandArgument
> {
> get
> {
> return commandArgument;
> }
>
> set
> {
> commandArgument = value;
> }
> }
>
> /// <summary>
> /// Gets or sets a value indicating whether validation is performed when
> the ConfirmButton control is clicked.
> /// </summary>
> [Bindable(false),
> Category("Behavior"),
> Description("Gets or sets a value indicating whether validation is
> performed when the ConfirmButton control is clicked."),
> DefaultValue(true)]
> public bool CausesValidation
> {
> get
> {
> return causesValidation;
> }
>
> set
> {
> causesValidation = value;
> }
> }
> #endregion
>
> #region Events
> /// <summary>
> /// Occurs when ConfirmButton control is clicked.
> /// </summary>
> public event EventHandler Click;
>
> /// <summary>
> /// Occurs when the ConfirmButton control is clicked.
> /// </summary>
> public event CommandEventHandler Command
> {
> add
> {
> base.Events.AddHandler(ConfirmButton.EventCommand,value);
> }
> remove
> {
> base.Events.RemoveHandler(ConfirmButton.EventCommand,value);
> }
> }
> #endregion
>
> #region IPostBackEventHandler Members
>
> /// <summary>
> /// Notifies the server control that caused the postback that it should
> handle an incoming post back event.
> /// </summary>
> /// <param name="eventArgument">The post-back argument.</param>
> public void RaisePostBackEvent(string eventArgument)
> {
> this.OnClick(this, new System.EventArgs());
> this.OnCommand(this,new
> CommandEventArgs(this.CommandName,this.CommandArgument));
> }
>
> #endregion
>
> }
> }
>
> --
> -Demetri