Asp.net Custom user control button. How to stop multiple clicks by user

两盒软妹~` 提交于 2019-12-12 04:31:10

问题


I am trying to modify an open source Forum called YetAnotherForum.net in the project they have a custom user control called Yaf:ThemeButton. Now its rendered as an anchor with an onclick method in this code

ThemeButton.cs

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

 namespace YAF.Controls
 {
 /// <summary>
 /// The theme button.
 /// </summary>
 public class ThemeButton : BaseControl, IPostBackEventHandler
{
/// <summary>
/// The _click event.
/// </summary>
protected static object _clickEvent = new object();

/// <summary>
/// The _command event.
/// </summary>
protected static object _commandEvent = new object();

/// <summary>
/// The _attribute collection.
/// </summary>
protected AttributeCollection _attributeCollection;

/// <summary>
/// The _localized label.
/// </summary>
protected LocalizedLabel _localizedLabel = new LocalizedLabel();

/// <summary>
/// The _theme image.
/// </summary>
protected ThemeImage _themeImage = new ThemeImage();

/// <summary>
/// Initializes a new instance of the <see cref="ThemeButton"/> class.
/// </summary>
public ThemeButton()
  : base()
{
  Load += new EventHandler(ThemeButton_Load);
  this._attributeCollection = new AttributeCollection(ViewState);
}

/// <summary>
/// ThemePage for the optional button image
/// </summary>
public string ImageThemePage
{
  get
  {
    return this._themeImage.ThemePage;
  }

  set
  {
    this._themeImage.ThemePage = value;
  }
}

/// <summary>
/// ThemeTag for the optional button image
/// </summary>
public string ImageThemeTag
{
  get
  {
    return this._themeImage.ThemeTag;
  }

  set
  {
    this._themeImage.ThemeTag = value;
  }
}

/// <summary>
/// Localized Page for the optional button text
/// </summary>
public string TextLocalizedPage
{
  get
  {
    return this._localizedLabel.LocalizedPage;
  }

  set
  {
    this._localizedLabel.LocalizedPage = value;
  }
}

/// <summary>
/// Localized Tag for the optional button text
/// </summary>
public string TextLocalizedTag
{
  get
  {
    return this._localizedLabel.LocalizedTag;
  }

  set
  {
    this._localizedLabel.LocalizedTag = value;
  }
}

/// <summary>
/// Defaults to "yafcssbutton"
/// </summary>
public string CssClass
{
  get
  {
    return (ViewState["CssClass"] != null) ? ViewState["CssClass"] as string : "yafcssbutton";
  }

  set
  {
    ViewState["CssClass"] = value;
  }
}

/// <summary>
/// Setting the link property will make this control non-postback.
/// </summary>
public string NavigateUrl
{
  get
  {
    return (ViewState["NavigateUrl"] != null) ? ViewState["NavigateUrl"] as string : string.Empty;
  }

  set
  {
    ViewState["NavigateUrl"] = value;
  }
}

/// <summary>
/// Localized Page for the optional link description (title)
/// </summary>
public string TitleLocalizedPage
{
  get
  {
    return (ViewState["TitleLocalizedPage"] != null) ? ViewState["TitleLocalizedPage"] as string : "BUTTON";
  }

  set
  {
    ViewState["TitleLocalizedPage"] = value;
  }
}

/// <summary>
/// Localized Tag for the optional link description (title)
/// </summary>
public string TitleLocalizedTag
{
  get
  {
    return (ViewState["TitleLocalizedTag"] != null) ? ViewState["TitleLocalizedTag"] as string : string.Empty;
  }

  set
  {
    ViewState["TitleLocalizedTag"] = value;
  }
}

/// <summary>
/// Non-localized Title for optional link description
/// </summary>
public string TitleNonLocalized
{
  get
  {
    return (ViewState["TitleNonLocalized"] != null) ? ViewState["TitleNonLocalized"] as string : string.Empty;
  }

  set
  {
    ViewState["TitleNonLocalized"] = value;
  }
}

/// <summary>
/// Gets Attributes.
/// </summary>
public AttributeCollection Attributes
{
  get
  {
    return this._attributeCollection;
  }
}

/// <summary>
/// Gets or sets CommandName.
/// </summary>
public string CommandName
{
  get
  {
    if (ViewState["commandName"] != null)
    {
      return ViewState["commandName"].ToString();
    }

    return null;
  }

  set
  {
    ViewState["commandName"] = value;
  }
}

/// <summary>
/// Gets or sets CommandArgument.
/// </summary>
public string CommandArgument
{
  get
  {
    if (ViewState["commandArgument"] != null)
    {
      return ViewState["commandArgument"].ToString();
    }

    return null;
  }

  set
  {
    ViewState["commandArgument"] = value;
  }
}

#region IPostBackEventHandler Members

/// <summary>
/// The i post back event handler. raise post back event.
/// </summary>
/// <param name="eventArgument">
/// The event argument.
/// </param>
void IPostBackEventHandler.RaisePostBackEvent(string eventArgument)
{
  OnCommand(new CommandEventArgs(CommandName, CommandArgument));
  OnClick(EventArgs.Empty);
}

#endregion

/// <summary>
/// Setup the controls before render
/// </summary>
/// <param name="sender">
/// </param>
/// <param name="e">
/// </param>
private void ThemeButton_Load(object sender, EventArgs e)
{
  if (!String.IsNullOrEmpty(this._themeImage.ThemeTag))
  {
    // add the theme image...
    Controls.Add(this._themeImage);
  }

  // render the text if available
  if (!String.IsNullOrEmpty(this._localizedLabel.LocalizedTag))
  {
    Controls.Add(this._localizedLabel);
  }
}

/// <summary>
/// The render.
/// </summary>
/// <param name="output">
/// The output.
/// </param>
protected override void Render(HtmlTextWriter output)
{
  // get the title...
  string title = GetLocalizedTitle();

  output.BeginRender();
  output.WriteBeginTag("a");
  output.WriteAttribute("id", ClientID);
  if (!String.IsNullOrEmpty(CssClass))
  {
    output.WriteAttribute("class", CssClass);
  }

  if (!String.IsNullOrEmpty(title))
  {
    output.WriteAttribute("title", title);
  }
  else if (!String.IsNullOrEmpty(TitleNonLocalized))
  {
    output.WriteAttribute("title", TitleNonLocalized);
  }

  if (!String.IsNullOrEmpty(NavigateUrl))
  {
    output.WriteAttribute("href", NavigateUrl.Replace("&", "&amp;"));
  }
  else
  {
    // string.Format("javascript:__doPostBack('{0}','{1}')",this.ClientID,""));
    output.WriteAttribute("href", Page.ClientScript.GetPostBackClientHyperlink(this, string.Empty));
  }

  bool wroteOnClick = false;

  // handle additional attributes (if any)
  if (this._attributeCollection.Count > 0)
  {
    // add attributes...
    foreach (string key in this._attributeCollection.Keys)
    {
      // get the attribute and write it...
      if (key.ToLower() == "onclick")
      {
        // special handling... add to it...
        output.WriteAttribute(key, string.Format("{0};{1}", this._attributeCollection[key], "this.blur();this.display='none';"));
        wroteOnClick = true;
      }
      else if (key.ToLower().StartsWith("on") || key.ToLower() == "rel" || key.ToLower() == "target")
      {
        // only write javascript attributes -- and a few other attributes...
        output.WriteAttribute(key, this._attributeCollection[key]);
      }
    }
  }

  // IE fix
  if (!wroteOnClick)
  {
      output.WriteAttribute("onclick", "this.blur();this.style.display='none';");
  }

  output.Write(HtmlTextWriter.TagRightChar);

  output.WriteBeginTag("span");
  output.Write(HtmlTextWriter.TagRightChar);

  // render the optional controls (if any)
  base.Render(output);
  output.WriteEndTag("span");

  output.WriteEndTag("a");
  output.EndRender();
}

/// <summary>
/// The get localized title.
/// </summary>
/// <returns>
/// The get localized title.
/// </returns>
protected string GetLocalizedTitle()
{
  if (Site != null && Site.DesignMode == true && !String.IsNullOrEmpty(TitleLocalizedTag))
  {
    return String.Format("[TITLE:{0}]", TitleLocalizedTag);
  }
  else if (!String.IsNullOrEmpty(TitleLocalizedPage) && !String.IsNullOrEmpty(TitleLocalizedTag))
  {
    return PageContext.Localization.GetText(TitleLocalizedPage, TitleLocalizedTag);
  }
  else if (!String.IsNullOrEmpty(TitleLocalizedTag))
  {
    return PageContext.Localization.GetText(TitleLocalizedTag);
  }

  return null;
}

/// <summary>
/// The on click.
/// </summary>
/// <param name="e">
/// The e.
/// </param>
protected virtual void OnClick(EventArgs e)
{
  var handler = (EventHandler) Events[_clickEvent];
  if (handler != null)
  {
    handler(this, e);
  }
}

/// <summary>
/// The on command.
/// </summary>
/// <param name="e">
/// The e.
/// </param>
protected virtual void OnCommand(CommandEventArgs e)
{
  var handler = (CommandEventHandler) Events[_commandEvent];

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

  RaiseBubbleEvent(this, e);
}

/// <summary>
/// The click.
/// </summary>
public event EventHandler Click
{
  add
  {
    Events.AddHandler(_clickEvent, value);
  }

  remove
  {
    Events.RemoveHandler(_clickEvent, value);
  }
}

/// <summary>
/// The command.
/// </summary>
public event CommandEventHandler Command
{
  add
  {
    Events.AddHandler(_commandEvent, value);
  }

  remove
  {
    Events.RemoveHandler(_commandEvent, value);
  }
}
}
}

now that is just cs file its handled like this in the .ascx page of the actual website

   <YAF:ThemeButton ID="Save" runat="server" CssClass="yafcssbigbutton leftItem" TextLocalizedTag="SAVE"
OnClick="Save_Click" />

now it is given an OnClick codebehind function that does some serverside function like this

  protected void Save_Click(object sender, EventArgs e)
  {
    //some serverside code here
  }

now I have a problem with the user being able to click multiple times and firing that serverside function multiple times. I have added in the code as of right now an extra onclick="this.style.display='none'" in the .cs code but that is a ugly fix I was wondering if anyone would have a better idea of disabling the ThemeButton clientside?? pls any feedback if I need to give more examples or further explain the question thanks.


回答1:


You could do something like this:

function disableClick(domNode) {
    // replace onclick event handler with a "return false"
    domNode.onclick = function() { return false; }

    // have a CSS class 'button-disabled' to set the text colour or whatever
    domNode.className = "button-disabled";
}

...

<a href="..." onclick="whatever; disableClick(this); return true;">click me</a>

That is, set the onclick handler to a function that simply returns false. This is assuming that the <YAF:ThemeButton> control renders as an <a> tag...




回答2:


I would try to place an OnClientClick in your button tag.

 <YAF:ThemeButton ID="Save" runat="server" CssClass="yafcssbigbutton leftItem" TextLocalizedTag="SAVE" OnClick="Save_Click" OnClientClick="this.disabled = true;" /> 

This should disable the button once clicked. Once the page reloads form the postBack, the button will be enabled again. Even though this is a custom control to YAF, it probably inheirits from the standard asp:button control which has the OnClienClick attribute.

Just some more info: MSDN



来源:https://stackoverflow.com/questions/2592229/asp-net-custom-user-control-button-how-to-stop-multiple-clicks-by-user

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!