Asp.net Пользовательская кнопка управления пользователем.Как остановить несколько кликов по пользователю - PullRequest
0 голосов
/ 07 апреля 2010

Я пытаюсь изменить форум с открытым исходным кодом под названием 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
  }

теперь у меня проблема с тем, что пользователь может щелкать несколько раз и запускать эту функцию на сервере несколько раз. На данный момент я добавил в код дополнительный onclick = "this.style.display = 'none'" в коде .cs, но это ужасное исправление. Мне было интересно, есть ли у кого-нибудь лучшая идея отключить ThemeButton? сторона клиента?? Пожалуйста, любые отзывы, если мне нужно дать больше примеров или более подробно объяснить вопрос спасибо.

Ответы [ 2 ]

1 голос
/ 07 апреля 2010

Вы можете сделать что-то вроде этого:

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> отображается как тег ...

0 голосов
/ 07 апреля 2010

Я бы попытался разместить 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

...