Quantcast
Channel: Development With A Dot
Viewing all articles
Browse latest Browse all 404

Extended ASP.NET Button Control

$
0
0

I once had the need to have a button control that would change its look depending on a theme, for example, it would render either as regular button, an image or a link. Of course, the only way I had to achieve this was by manually swapping the Button control for a ImageButton or a LinkButton, which wasn’t really a solution, so I started to think of a control that could do the trick… and here it is!

Basically, I wrote a button control that displays in one of 5 ways:

  • A regular button:
image
  • A text hyperlink:

image

  • An image:

image

  • A button with HTML content (see this):

image

  • A hyperlink with HTML content:

image

In ASP.NET terms, I have a server-side control with a ButtonType property. The markup that produces each effect is as follows:

   1:<web:ExtendedButtonrunat="server"ButtonType="Button"ID="button"Text="Button"/>
   2:  
   3:<web:ExtendedButtonrunat="server"ButtonType="Link"ID="link"Text="Link"/>
   4:  
   5:<web:ExtendedButtonrunat="server"ButtonType="Image"ID="image"ImageUrl="~/Images/button.png"/>
   6:  
   7:<web:ExtendedButtonrunat="server"ButtonType="Button"ID="buttonWithTemplate">
   8:<Template>
   9:<asp:Imagerunat="server"ImageUrl="~/Images/button.png"/>
  10:             Button With Template
  11:</Template>
  12:</web:ExtendedButton>
  13:  
  14:<web:ExtendedButtonrunat="server"ButtonType="Link"ID="linkWithTemplate">
  15:<Template>
  16:<asp:Imagerunat="server"ImageUrl="~/Images/button.png"/>
  17:             Link With Template
  18:</Template>
  19:</web:ExtendedButton>

For the Image value of ButtonType, the only useful properties are ImageUrl, ImageAlign and AlternateText. These will work in the exact same way as the ImageButton control.

For Link and Button, if the Template property is not specified, Text will be used for the textual description of the button or link. If instead a Template is available, it will be used instead of the Text. Keep in mind that you can specify almost any HTML you like for the Template, as long as it can be surrounded by an A (in the case of the Link type) or BUTTON (for Button) tags. If no Template is supplied, it will render and behave just like a LinkButton or a Button.

This control implements IButtonControl, so it shares the usual behavior of regular button controls, like having a text property, a validation group, a postback URL, Click and Command events, event bubbling, etc. It uses the control state to save some properties, so it is safe to turn off view state in it.

I almost forgot: here is the code!

   1: [ParseChildren(true)]
   2: [DefaultEvent("Click")]
   3: [PersistChildren(false)]
   4: [DefaultProperty("Text")]
   5: [SupportsEventValidation]
   6: [ToolboxData("<{0}:ExtendedButton runat=\"server\" Text=\"\" />")]
   7:publicclass ExtendedButton : WebControl, IButtonControl, IPostBackEventHandler, INamingContainer, ITextControl, IPostBackDataHandler
   8: {
   9:#region Private staticreadonly fields
  10:privatestaticreadonly Object EventClick = new Object();
  11:privatestaticreadonly Object EventCommand = new Object();
  12:#endregion
  13:  
  14:#region Public constructor
  15:public ExtendedButton() : base(HtmlTextWriterTag.Input)
  16:     {
  17:this.ButtonType = ButtonType.Button;
  18:this.CommandArgument = String.Empty;
  19:this.CommandName = String.Empty;
  20:this.OnClientClick = String.Empty;
  21:this.ImageAlign = ImageAlign.NotSet;
  22:this.ImageUrl = String.Empty;
  23:this.PostBackUrl = String.Empty;
  24:this.CausesValidation = true;
  25:this.ValidationGroup = String.Empty;
  26:this.UseSubmitBehavior = true;
  27:this.Text = String.Empty;
  28:     }
  29:#endregion
  30:  
  31:#region Protected override methods
  32:protectedoverridevoid AddAttributesToRender(HtmlTextWriter writer)
  33:     {
  34:base.AddAttributesToRender(writer);
  35:  
  36:this.Page.VerifyRenderingInServerForm(this);
  37:  
  38:if (this.ButtonType == ButtonType.Button)
  39:         {
  40:if (this.Template == null)
  41:             {
  42:if (this.UseSubmitBehavior == true)
  43:                 {
  44:                     writer.AddAttribute(HtmlTextWriterAttribute.Type, "submit");
  45:                 }
  46:else
  47:                 {
  48:                     writer.AddAttribute(HtmlTextWriterAttribute.Type, "button");
  49:                 }
  50:             }
  51:  
  52:             writer.AddAttribute(HtmlTextWriterAttribute.Value, this.Text);
  53:             writer.AddAttribute(HtmlTextWriterAttribute.Name, this.UniqueID);
  54:         }
  55:elseif (this.ButtonType == ButtonType.Image)
  56:         {
  57:             writer.AddAttribute(HtmlTextWriterAttribute.Name, this.UniqueID);
  58:             writer.AddAttribute(HtmlTextWriterAttribute.Value, this.Text);
  59:             writer.AddAttribute(HtmlTextWriterAttribute.Alt, this.AlternateText);
  60:             writer.AddAttribute(HtmlTextWriterAttribute.Type, "image");
  61:             writer.AddAttribute(HtmlTextWriterAttribute.Src, HttpUtility.HtmlEncode(this.ResolveClientUrl(this.ImageUrl)));
  62:  
  63:if (this.ImageAlign != ImageAlign.NotSet)
  64:             {
  65:                 writer.AddAttribute(HtmlTextWriterAttribute.Align, this.ImageAlign.ToString().ToLower());
  66:             }
  67:         }
  68:  
  69:         String firstScript = this.OnClientClick;
  70:         PostBackOptions postBackOptions = this.GetPostBackOptions();
  71:
  72:if (this.IsEnabled == true)
  73:         {
  74:if (this.HasAttributes == true)
  75:             {
  76:                 String script = this.Attributes[HtmlTextWriterAttribute.Onclick.ToString()];
  77:  
  78:if (String.IsNullOrWhitespace(script) == false)
  79:                 {
  80:                     firstScript = String.Join(";", new String[] { firstScript, script });
  81:this.Attributes.Remove(HtmlTextWriterAttribute.Onclick.ToString());
  82:                 }
  83:             }
  84:  
  85:             String postBackEventReference = this.Page.ClientScript.GetPostBackEventReference(postBackOptions, true);
  86:  
  87:if (String.IsNullOrWhiteSpace(postBackEventReference) == false)
  88:             {
  89:                 firstScript = firstScript + postBackEventReference;
  90:  
  91:if ((this.ButtonType == ButtonType.Link) || ((this.ButtonType == ButtonType.Button) && (this.Template != null)))
  92:                 {
  93:                     writer.AddAttribute(HtmlTextWriterAttribute.Href, postBackEventReference);
  94:                 }
  95:             }
  96:else
  97:             {
  98:if (this.ButtonType == ButtonType.Link)
  99:                 {
 100:                     writer.AddAttribute(HtmlTextWriterAttribute.Href, "javascript:void(0)");
 101:                 }
 102:             }
 103:         }
 104:  
 105:if (firstScript.Length > 0)
 106:         {
 107:if (this.ButtonType == ButtonType.Button)
 108:             {
 109:if (this.UseSubmitBehavior == false)
 110:                 {
 111:                     writer.AddAttribute(HtmlTextWriterAttribute.Onclick, firstScript);
 112:                 }
 113:             }
 114:else
 115:             {
 116:if (String.IsNullOrWhiteSpace(this.OnClientClick) == false)
 117:                 {
 118:                     writer.AddAttribute(HtmlTextWriterAttribute.Onclick, this.OnClientClick);
 119:                 }
 120:             }
 121:         }
 122:  
 123:if ((this.Enabled == true) && (this.IsEnabled == false))
 124:         {
 125:             writer.AddAttribute(HtmlTextWriterAttribute.Disabled, HtmlTextWriterAttribute.Disabled.ToString().ToLower());
 126:         }
 127:     }
 128:  
 129:protectedoverridevoid OnInit(EventArgs e)
 130:     {
 131:this.Page.RegisterRequiresControlState(this);
 132:  
 133:if (this.ButtonType == ButtonType.Image)
 134:         {
 135:this.Page.RegisterRequiresPostBack(this);
 136:         }
 137:  
 138:base.OnInit(e);
 139:     }
 140:  
 141:protectedoverridevoid RenderContents(HtmlTextWriter writer)
 142:     {
 143:if ((this.ButtonType == ButtonType.Link) || (this.ButtonType == ButtonType.Button))
 144:         {
 145:if (this.Template != null)
 146:             {
 147:                 PlaceHolder placeHolder = new PlaceHolder();
 148:this.Template.InstantiateIn(placeHolder);
 149:this.Controls.Add(placeHolder);
 150:base.RenderContents(writer);
 151:             }
 152:else
 153:             {
 154:if (this.ButtonType == ButtonType.Link)
 155:                 {
 156:                     writer.WriteEncodedText(this.Text);
 157:                 }
 158:             }
 159:         }
 160:     }
 161:  
 162:protectedoverridevoid LoadControlState(Object savedState)
 163:     {
 164:         Object [] state = savedState as Object [];
 165:  
 166:this.OnClientClick = (String) state [ 1 ];
 167:this.CausesValidation = (Boolean) state [ 2 ];
 168:this.ValidationGroup = (String) state [ 3 ];
 169:this.ButtonType = (ButtonType) state [ 4 ];
 170:this.PostBackUrl = (String) state [ 5 ];
 171:this.UseSubmitBehavior = (Boolean) state [ 6 ];
 172:this.CommandArgument = (String) state [ 7 ];
 173:this.CommandName = (String) state [ 8 ];
 174:this.Text = (String) state [ 9 ];
 175:this.ImageUrl = (String) state [ 10 ];
 176:this.ImageAlign = (ImageAlign) state [ 11 ];
 177:  
 178:base.LoadControlState(state [ 0 ]);
 179:     }
 180:  
 181:protectedoverride Object SaveControlState()
 182:     {
 183:         Object [] state = new Object [] { base.SaveControlState(), this.OnClientClick, this.CausesValidation, this.ValidationGroup, this.ButtonType, this.PostBackUrl, this.UseSubmitBehavior, this.CommandArgument, this.CommandName, this.Text, this.ImageUrl, this.ImageAlign };
 184:return (state);
 185:     }
 186:#endregion
 187:  
 188:#region Public override methods
 189:publicoverridevoid RenderBeginTag(HtmlTextWriter writer)
 190:     {
 191:this.AddAttributesToRender(writer);
 192:  
 193:switch (this.ButtonType)
 194:         {
 195:case ButtonType.Button:
 196:if (this.Template != null)
 197:                 {
 198:                     writer.RenderBeginTag(HtmlTextWriterTag.Button);
 199:                 }
 200:else
 201:                 {
 202:                     writer.RenderBeginTag(HtmlTextWriterTag.Input);
 203:                 }
 204:break;
 205:  
 206:case ButtonType.Image:
 207:                 writer.RenderBeginTag(HtmlTextWriterTag.Input);
 208:break;
 209:  
 210:case ButtonType.Link:
 211:                 writer.RenderBeginTag(HtmlTextWriterTag.A);
 212:break;
 213:         }
 214:     }
 215:#endregion
 216:  
 217:#region Protected virtual methods
 218:protectedvirtual PostBackOptions GetPostBackOptions()
 219:     {
 220:         PostBackOptions options = new PostBackOptions(this, String.Empty);
 221:         options.ClientSubmit = false;
 222:  
 223:if ((this.CausesValidation == true) && (this.Page.GetValidators(this.ValidationGroup).Count > 0))
 224:         {
 225:             options.PerformValidation = true;
 226:             options.ValidationGroup = this.ValidationGroup;
 227:         }
 228:  
 229:if (String.IsNullOrWhiteSpace(this.PostBackUrl) == false)
 230:         {
 231:             options.ActionUrl = HttpUtility.UrlPathEncode(this.ResolveClientUrl(this.PostBackUrl));
 232:         }
 233:  
 234:if ((this.ButtonType == ButtonType.Link) || ((this.ButtonType == ButtonType.Button) && (this.Template != null)))
 235:         {
 236:             options.ClientSubmit = true;
 237:             options.RequiresJavaScriptProtocol = true;
 238:         }
 239:  
 240:return (options);
 241:     }
 242:  
 243:protectedvirtualvoid OnClick(EventArgs e)
 244:     {
 245:         EventHandler handler = (EventHandler) this.Events [ EventClick ];
 246:  
 247:if (handler != null)
 248:         {
 249:             handler(this, e);
 250:         }
 251:     }
 252:  
 253:protectedvirtualvoid OnCommand(CommandEventArgs e)
 254:     {
 255:         CommandEventHandler handler = (CommandEventHandler) this.Events [ EventCommand ];
 256:  
 257:if (handler != null)
 258:         {
 259:             handler(this, e);
 260:         }
 261:     }
 262:#endregion
 263:  
 264:#region IButtonControl Members
 265:publicevent EventHandler Click
 266:     {
 267:         add
 268:         {
 269:this.Events.AddHandler(EventClick, value);
 270:         }
 271:         remove
 272:         {
 273:this.Events.RemoveHandler(EventClick, value);
 274:         }
 275:     }
 276:  
 277:publicevent CommandEventHandler Command
 278:     {
 279:         add
 280:         {
 281:this.Events.AddHandler(EventCommand, value);
 282:         }
 283:         remove
 284:         {
 285:this.Events.RemoveHandler(EventCommand, value);
 286:         }
 287:     }
 288:  
 289:     [DefaultValue(true)]
 290:     [Themeable(false)]
 291:public Boolean CausesValidation
 292:     {
 293:         get;
 294:         set;
 295:     }
 296:  
 297:     [Bindable(true)]
 298:     [DefaultValue("")]
 299:     [Themeable(false)]
 300:public String CommandArgument
 301:     {
 302:         get;
 303:         set;
 304:     }
 305:  
 306:     [Themeable(false)]
 307:     [DefaultValue("")]
 308:public String CommandName
 309:     {
 310:         get;
 311:         set;
 312:     }
 313:  
 314:     [DefaultValue("")]
 315:     [Themeable(false)]
 316:     [UrlProperty("*.aspx")]
 317:public String PostBackUrl
 318:     {
 319:         get;
 320:         set;
 321:     }
 322:  
 323:     [DefaultValue("")]
 324:     [Themeable(false)]
 325:public String ValidationGroup
 326:     {
 327:         get;
 328:         set;
 329:     }
 330:  
 331:     [DefaultValue("")]
 332:     [Localizable(true)]
 333:     [Bindable(true)]
 334:public String Text
 335:     {
 336:         get;
 337:         set;
 338:     }
 339:#endregion
 340:  
 341:#region Public properties
 342:     [Browsable(false)]
 343:     [TemplateContainer(typeof(ExtendedButton))]
 344:     [TemplateInstance(TemplateInstance.Single)]
 345:     [PersistenceMode(PersistenceMode.InnerProperty)]
 346:public ITemplate Template
 347:     {
 348:         get;
 349:         set;
 350:     }
 351:  
 352:     [DefaultValue(ButtonType.Button)]
 353:public ButtonType ButtonType
 354:     {
 355:         get;
 356:         set;
 357:     }
 358:  
 359:     [Themeable(false)]
 360:     [DefaultValue("")]
 361:public String OnClientClick
 362:     {
 363:         get;
 364:         set;
 365:     }
 366:  
 367:     [DefaultValue("")]
 368:     [Themeable(false)]
 369:     [UrlProperty("*.jpg;*.gif;*.png")]
 370:public String ImageUrl
 371:     {
 372:         get;
 373:         set;
 374:     }
 375:  
 376:     [DefaultValue(ImageAlign.NotSet)]
 377:public ImageAlign ImageAlign
 378:     {
 379:         get;
 380:         set;
 381:     }
 382:  
 383:     [DefaultValue("")]
 384:     [Themeable(false)]
 385:public String AlternateText
 386:     {
 387:         get;
 388:         set;
 389:     }
 390:  
 391:     [DefaultValue(true)]
 392:     [Themeable(false)]
 393:public Boolean UseSubmitBehavior
 394:     {
 395:         get;
 396:         set;
 397:     }
 398:#endregion
 399:  
 400:#region IPostBackEventHandler Members
 401:void IPostBackEventHandler.RaisePostBackEvent(String eventArgument)
 402:     {
 403:this.Page.ClientScript.ValidateEvent(this.UniqueID, eventArgument);
 404:  
 405:if (this.CausesValidation == true)
 406:         {
 407:this.Page.Validate(this.ValidationGroup);
 408:         }
 409:  
 410:this.OnClick(EventArgs.Empty);
 411:this.OnCommand(new CommandEventArgs(this.CommandName, this.CommandArgument));
 412:  
 413:this.RaiseBubbleEvent(this, EventArgs.Empty);
 414:     }
 415:#endregion
 416:  
 417:#region IPostBackDataHandler Members
 418:  
 419:     Boolean IPostBackDataHandler.LoadPostData(String postDataKey, NameValueCollection postCollection)
 420:     {
 421:if (postDataKey == this.UniqueID)
 422:         {
 423:if (this.ButtonType == ButtonType.Image)
 424:             {
 425:if ((String.IsNullOrWhiteSpace(postCollection[postDataKey + ".x"]) == false) && (String.IsNullOrWhiteSpace(postCollection[postDataKey + ".y"]) == false))
 426:                 {
 427:                     (thisas IPostBackEventHandler).RaisePostBackEvent(String.Empty);                    
 428:                 }
 429:             }
 430:else
 431:             {
 432:                 (thisas IPostBackEventHandler).RaisePostBackEvent(String.Empty);
 433:             }
 434:         }
 435:  
 436:return(false);
 437:     }
 438:  
 439:void IPostBackDataHandler.RaisePostDataChangedEvent()
 440:     {
 441:     }
 442:  
 443:#endregion
 444: }

As usual, I hope you find it useful!


Viewing all articles
Browse latest Browse all 404

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>