Asp.net 自定义用户控制按钮。如何阻止用户多次点击
我正在尝试修改一个名为 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("&", "&"));
}
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客户端??如果我需要提供更多示例或进一步解释问题,请提供任何反馈,谢谢。
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("&", "&"));
}
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以执行以下操作:
即将 onclick 处理程序设置为仅返回 false 的函数。这是假设
控件呈现为 。标签...You could do something like this:
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...我会尝试在您的按钮标签中放置一个 OnClientClick 。
单击后,该按钮将被禁用。一旦页面从回发重新加载,该按钮将再次启用。尽管这是 YAF 的自定义控件,但它可能继承自具有 OnClienClick 属性的标准 asp:button 控件。
只是更多信息:MSDN
I would try to place an OnClientClick in your button tag.
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