Skip to content

Instantly share code, notes, and snippets.

@rmack005
Forked from alassek/ModernButton.cs
Created April 27, 2011 16:35
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save rmack005/944619 to your computer and use it in GitHub Desktop.
Save rmack005/944619 to your computer and use it in GitHub Desktop.
ASP.Net Button control that renders with Button tag instead of input
using System;
using System.ComponentModel;
using System.Web;
using System.Web.UI;
using System.Linq;
namespace Public.Html.Controls
{
public enum ButtonType
{
Submit,
Reset,
Button
} ;
[ToolboxData("<{0}:Button runat=server></{0}:Button>")]
[ParseChildren(false)]
[PersistChildren(true)]
public class Button : System.Web.UI.WebControls.WebControl, IPostBackDataHandler
{
//Fields
private static readonly object EventClick = new object();
private static readonly object EventCommand = new object();
private static readonly object EventValueChanged = new object();
//Events
public event EventHandler Click
{
add { Events.AddHandler(EventClick, value); }
remove { Events.RemoveHandler(EventClick, value); }
}
public event EventHandler ValueChanged
{
add { Events.AddHandler(EventValueChanged, value); }
remove { Events.RemoveHandler(EventValueChanged, value); }
}
public event System.Web.UI.WebControls.CommandEventHandler Command
{
add { Events.AddHandler(EventCommand, value); }
remove { Events.RemoveHandler(EventCommand, value); }
}
public Button()
: base(HtmlTextWriterTag.Button)
{
}
#region Properties
[Category("Behavior")]
[DefaultValue("")]
public string CommandArgument
{
get
{
return ViewState["CommandArgument"] as string ?? string.Empty;
}
set
{
ViewState["CommandArgument"] = value;
}
}
[Category("Behavior")]
[DefaultValue("")]
public string CommandName
{
get
{
return ViewState["CommandName"] as string ?? string.Empty;
}
set
{
ViewState["CommandName"] = value;
}
}
[Category("Behavior")]
[DefaultValue("")]
public virtual string PostBackUrl
{
get
{
return ViewState["PostBackUrl"] as string ?? string.Empty;
}
set
{
ViewState["PostBackUrl"] = value;
}
}
[Category("Validation")]
[DefaultValue(true)]
public virtual bool CausesValidation
{
get
{
var causesValidation = ViewState["CausesValidation"];
return (causesValidation == null) ? true : (bool)causesValidation;
}
set
{
ViewState["CausesValidation"] = value;
}
}
[Category("Validation")]
[DefaultValue("")]
public virtual string ValidationGroup
{
get
{
return ViewState["ValidationGroup"] as string ?? string.Empty;
}
set
{
ViewState["ValidationGroup"] = value;
}
}
[Category("Behavior")]
[DefaultValue("")]
public string Value
{
get
{
return ViewState["Value"] as string ?? string.Empty;
}
set { ViewState["Value"] = value; }
}
[Category("Behavior")]
[DefaultValue(ButtonType.Button)]
[Description("Defines the type of the button.")]
public ButtonType ButtonType
{
get
{
var obj = ViewState["ButtonType"];
return (obj == null) ? ButtonType.Button : (ButtonType) obj;
}
set { ViewState["ButtonType"] = value; }
}
#endregion
#region Methods
protected override void AddAttributesToRender(HtmlTextWriter writer)
{
base.AddAttributesToRender(writer);
if(!string.IsNullOrEmpty(Value))
writer.AddAttribute(HtmlTextWriterAttribute.Value, Value);
writer.AddAttribute(HtmlTextWriterAttribute.Type, ButtonType.ToString().ToLower());
var postBackOptions = GetPostBackOptions();
if(postBackOptions == null)
throw new Exception("postBackOptions must not be null");
if (postBackOptions.TargetControl == this)
{
writer.AddAttribute(HtmlTextWriterAttribute.Name, ClientID);
}
if (Page != null)
{
Page.ClientScript.RegisterForEventValidation(postBackOptions);
}
}
protected virtual PostBackOptions GetPostBackOptions()
{
var options = new PostBackOptions(this, string.Empty) { ClientSubmit = false };
if (Page != null)
{
if (CausesValidation && (Page.GetValidators(ValidationGroup).Count > 0))
{
options.PerformValidation = true;
options.ValidationGroup = ValidationGroup;
}
if (!String.IsNullOrEmpty(PostBackUrl))
{
options.ActionUrl = HttpUtility.UrlPathEncode(ResolveClientUrl(PostBackUrl));
}
}
return options;
}
protected void OnClick()
{
var handler = (EventHandler)Events[EventClick];
if (handler != null) handler(this, new EventArgs());
}
protected void OnValueChanged()
{
var handler = (EventHandler)Events[EventValueChanged];
if (handler != null) handler(this, new EventArgs());
}
protected void OnCommand(string commandName, string commandArgument)
{
var handler = (System.Web.UI.WebControls.CommandEventHandler)Events[EventCommand];
var args = new System.Web.UI.WebControls.CommandEventArgs(commandName, commandArgument);
if (handler != null) handler(this, args);
RaiseBubbleEvent(this, args);
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
if (Page != null)
Page.RegisterRequiresPostBack(this);
}
protected override void LoadControlState(object savedState)
{
var pair = savedState as Pair;
var str = savedState as string;
if(pair != null)
{
base.LoadControlState(pair.First);
Value = (string) pair.Second;
}
if(str != null)
{
Value = str;
}
}
protected override object SaveControlState()
{
var baseState = base.SaveControlState();
if (baseState == null)
return string.IsNullOrEmpty(Value) ? null : Value;
return new Pair(baseState, Value);
}
#endregion
#region IPostBackDataHandler
public bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)
{
if (string.IsNullOrEmpty(postDataKey))
throw new ArgumentOutOfRangeException("postDataKey");
if (postCollection == null)
throw new ArgumentNullException("postCollection");
if (postCollection.AllKeys.Contains(ClientID))
{
var existingValue = Value;
Value = postCollection[ClientID];
OnClick();
if(!string.IsNullOrEmpty(CommandName))
OnCommand(CommandName, CommandArgument);
return (existingValue.Equals(Value, StringComparison.Ordinal));
}
return false;
}
public void RaisePostDataChangedEvent()
{
OnValueChanged();
}
#endregion
}
}
@nottrobin
Copy link

How do I use this?

I included this class in my project, but I can't work out how to reference a Public.Html.Controls.Button rather than a System.Web.UI.WebControls.Button inside my .ascx file - asp:button always seems to create a System.Web.UI.WebControls.Button.

@jdnichollsc
Copy link

Server Error in '/' Application.

Page.IsValid cannot be called before validation has taken place. It should be queried in the event handler for a control that has CausesValidation=True and initiated the postback, or after a call to Page.Validate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment