Asp.net自定义用户控制按钮。如何阻止用户多次点击

时间:2010-04-07 12:06:26

标签: c# asp.net custom-controls anchor forums

我正在尝试在项目中修改一个名为YetAnotherForum.net的开源论坛,他们有一个名为Yaf:ThemeButton的自定义用户控件。现在它在此代码中使用onclick方法呈现为锚点

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);
  }
}
}
}

现在这只是cs文件,它在实际网站的.ascx页面中这样处理

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

现在给它一个OnClick代码隐藏函数,它可以像这样执行一些服务器端函数

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

现在我遇到一个问题,即用户可以多次单击并多次触发该服务器端功能。我已经在代码中添加了.cs代码中的额外onclick =“this.style.display ='none'”,但这是一个丑陋的修复我想知道是否有人会更好地禁用ThemeButton客户端??如果我需要提供更多的例子或进一步解释问题,请给我任何反馈意见。

2 个答案:

答案 0 :(得分:1)

你可以这样做:

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>

也就是说,将onclick处理程序设置为只返回false的函数。这假设<YAF:ThemeButton>控件呈现为&lt; a&gt;标签...

答案 1 :(得分:0)

我会尝试在按钮标记中放置一个OnClientClick。

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

这应该在点击后禁用按钮。页面从postBack重新加载后,该按钮将再次启用。虽然这是YAF的自定义控件,但它可能来自标准的asp:button控件,它具有OnClienClick属性。

更多信息:MSDN