One of the most common tasks we perform as ASP.NET developers is adding validated fields to a form.  Typically, this involves adding:

  • a label to tell the user what information is expected
  • a TextBox, DropDrown, CheckBox or other element to collect the data
  • a Validator to check whether the data entered is good or not


Rather than always adding these three elements, we can combine them into a single reusable server control.  The less elements we need to add to a page, the less time it takes to do so.

 

 

Step 1:  RequiredInput abstract class


An abstract class is a base class that has no implementation of its own.  It must be used as a building block for another class.  Since each type of input (TextBox, DropDownList, etc) has a slightly different implentation, We can collect all of the functionality that is common to each and put them into the RequiredInput abstract class, which is what we will use as the base class for our other controls such as the Required TextBox.

[NOTE:  Since I'm using Visual Studio 2008, I used the newer Automatic Properties.  This project is written for and completely compatible with the .NET 2.0 Framework.  If you're going to be using Visual Studio 2005 to edit this project, you will need to implement private variables]


   1:   
   2:  using System.ComponentModel;
   3:  using System.Web.UI.WebControls;
   4:  using System.Web.UI;
   5:   
   6:  namespace OurCurrentFuture
   7:  {
   8:      /// <summary>
   9:      /// A base for Labeled, Required Form Fields 
  10:      /// </summary>
  11:      public abstract class RequiredInput : CompositeControl
  12:      {
  13:          #region " Members "
  14:   
  15:          protected RequiredFieldValidator rfvValidator;
  16:          private bool _required = true;
  17:          protected Label lblLabel;
  18:   
  19:          #endregion
  20:   
  21:          #region " Properties "
  22:          /// <summary>
  23:          /// Different positions for the Label
  24:          /// </summary>
  25:          public enum LabelPosition
  26:          {
  27:              /// <summary>
  28:              /// Places the Label before the input
  29:              /// </summary>
  30:              Before,
  31:              /// <summary>
  32:              /// Places the Label after the input
  33:              /// </summary>
  34:              After
  35:          }
  36:   
  37:          /// <summary>
  38:          /// Gets or sets the label.
  39:          /// </summary>
  40:          /// <value>The label.</value>
  41:          [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
  42:          public Label Label
  43:          {
  44:              get;
  45:              set;
  46:          }
  47:   
  48:          /// <summary>
  49:          /// Gets or sets the label location.
  50:          /// </summary>
  51:          /// <value>The label location.</value>
  52:          public LabelPosition LabelLocation
  53:          {
  54:              get;
  55:              set;
  56:          }
  57:   
  58:          /// <summary>
  59:          /// Gets or sets a value indicating whether this <see cref="RequiredInput" /> is required.
  60:          /// </summary>
  61:          /// <value><c>true</c> if required; otherwise, <c>false</c>.</value>
  62:          public bool Required
  63:          {
  64:              get
  65:              {
  66:                  return _required;
  67:              }
  68:              set
  69:              {
  70:                  rfvValidator.Enabled = value;
  71:                  _required = value;
  72:              }
  73:          }
  74:   
  75:          /// <summary>
  76:          /// Gets or sets the validator.
  77:          /// </summary>
  78:          /// <value>The validator.</value>
  79:          [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
  80:          public RequiredFieldValidator Validator
  81:          {
  82:              get;
  83:              set;
  84:          }
  85:   
  86:          #endregion
  87:   
  88:          #region " Constructors "
  89:   
  90:          /// <summary>
  91:          /// Initializes a new instance of the <see cref="RequiredInput" /> class.
  92:          /// </summary>
  93:          public RequiredInput()
  94:          {
  95:              EnsureChildControls();
  96:              LabelLocation = LabelPosition.Before;
  97:              Validator.Text = "*";
  98:              Validator.Display = ValidatorDisplay.Dynamic;
  99:          }
 100:   
 101:          #endregion
 102:   
 103:          #region " Methods "
 104:   
 105:          /// <summary>
 106:          /// Renders the label.
 107:          /// </summary>
 108:          /// <param name="writer">The writer.</param>
 109:          protected void RenderLabel(HtmlTextWriter writer)
 110:          {
 111:              Label.RenderControl(writer);
 112:              writer.Write(writer.NewLine);
 113:   
 114:              if (string.IsNullOrEmpty(Validator.ErrorMessage) && !string.IsNullOrEmpty(Label.Text))
 115:              {
 116:                  Validator.ErrorMessage = string.Format("{0} is Required", Label.Text);
 117:              }
 118:   
 119:              Validator.RenderControl(writer);
 120:              writer.Write(writer.NewLine);
 121:   
 122:          }
 123:   
 124:          /// <summary>
 125:          /// Called by the ASP.NET page framework to notify server controls that use composition-based 
implementation to create any child controls they contain in preparation for posting back or rendering.
 126:          /// </summary>
 127:          protected override void CreateChildControls()
 128:          {
 129:              Label = new Label();
 130:              Label.ID = "lblLabel";
 131:   
 132:              Validator = new RequiredFieldValidator();
 133:              Validator.ID = "rvfValidator";
 134:          }
 135:   
 136:          #endregion
 137:      }
 138:  }
}

 

Let's take a look at some of the important pieces there:

public abstract class RequiredInput : CompositeControl

I'm deriving RequiredInput from the CompositeControl class.  This gives me some of the ASP.NET plumbing I need to create a control.

LabelPosition - An Enum allowing use to easily specify whether we want the Label control before or after the Input control

[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public Label Label


[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public RequiredFieldValidator Validator


Here, we've used the DesignerSerializationVisibility attribute set to "Contents" to specify that the designer should expose the properties of the underlying object.  This will allow us to easily set the properties of the Label and Validator from our own server control later on.

In the constructor, we first call EnsureChildControls.  This checks to see if we have already created the controls that are going in our server control.  

If they have not been created yet, then CreateChildControls is called to make sure they are available for us to work with.  CreateChildControls simply creates the Label and Validator objects.  If we tried to set properties before these objects were created, we'd get Null Reference Exceptions.

Finally, we have the RenderLabel method which is used by the control to actually generate the HTML for the Label and the Validator.  In order to make it even esier to use this control, we'll set the Validator.ErrorMessage property to a simple default if the ErrorMessage value is empty, but the Label is set.  That way we don't have to specify the ErrorMessage, but it's still populated with something useful.

 

Step 2:  RequiredTextBox Control

 

   1:  using System;
   2:  using System.ComponentModel;
   3:  using System.Web.UI;
   4:  using System.Web.UI.WebControls;
   5:   
   6:  namespace OurCurrentFuture
   7:  {
   8:      /// <summary>
   9:      /// A Textbox with a built in label control and RequiredFieldValidator
  10:      /// </summary>
  11:      [ValidationPropertyAttribute("Text")]
  12:      public class RequiredTextBox : RequiredInput
  13:      {
  14:   
  15:          #region "Properties"
  16:   
  17:          /// <summary>
  18:          /// Gets or sets the text.
  19:          /// </summary>
  20:          /// <value>The text.</value>
  21:          [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
  22:          public TextBox TextBox
  23:          {
  24:              get;
  25:              set;
  26:          }
  27:   
  28:   
  29:          /// <summary>
  30:          /// Gets or sets the text.
  31:          /// </summary>
  32:          /// <value>The text.</value>
  33:          public string Text
  34:          {
  35:              get
  36:              {
  37:                  return TextBox.Text;
  38:              }
  39:              set
  40:              {
  41:                  TextBox.Text = value;
  42:              }
  43:          }
  44:          #endregion
  45:   
  46:          #region "Constructors"
  47:   
  48:          /// <summary>
  49:          /// Initializes a new instance of the <see cref="RequiredTextBox" /> class.
  50:          /// </summary>
  51:          public RequiredTextBox()
  52:          {
  53:              EnsureChildControls();
  54:          }
  55:   
  56:          #endregion
  57:   
  58:          #region "Methods"
  59:   
  60:          /// <summary>
  61:          /// Called by the ASP.NET page framework to notify server controls that use composition-based
implementation to create any child controls they contain in preparation for posting back or rendering.
  62:          /// </summary>
  63:          protected override void CreateChildControls()
  64:          {
  65:              base.CreateChildControls();
  66:   
  67:              TextBox = new TextBox();
  68:              TextBox.ID = "vtbTextBox";
  69:              Controls.Add(TextBox);
  70:   
  71:              Label.AssociatedControlID = TextBox.ID;
  72:              Controls.Add(Label);
  73:   
  74:              Controls.Add(Validator);
  75:              Validator.ControlToValidate = TextBox.ID;
  76:              if (string.IsNullOrEmpty(Validator.ErrorMessage) && !string.IsNullOrEmpty(Label.Text))
  77:              {
  78:                  Validator.ErrorMessage = String.Format("{0} is Required", Label);
  79:              }
  80:              Validator.Enabled = Required;
  81:          }
  82:   
  83:   
  84:          /// <summary>
  85:          /// Writes the <see cref="T:System.Web.UI.WebControls.CompositeControl" /> content to the 
specified <see cref="T:System.Web.UI.HtmlTextWriter" /> object, for display on the client.
  86:          /// </summary>
  87:          /// <param name="writer">An <see cref="T:System.Web.UI.HtmlTextWriter" /> that represents 
the output stream to render HTML content on the client.</param>
  88:          protected override void Render(HtmlTextWriter writer)
  89:          {
  90:              if (!string.IsNullOrEmpty(CssClass))
  91:              {
  92:                  writer.AddAttribute("class", CssClass);
  93:              }
  94:   
  95:              writer.RenderBeginTag("div");
  96:   
  97:              if (LabelLocation == LabelPosition.Before)
  98:              {
  99:                  RenderLabel(writer);
 100:              }
 101:   
 102:              TextBox.RenderControl(writer);
 103:              writer.Write(writer.NewLine);
 104:   
 105:              if (LabelLocation == LabelPosition.After)
 106:              {
 107:                  RenderLabel(writer);
 108:              }
 109:   
 110:              writer.RenderEndTag();
 111:          }
 112:   
 113:          #endregion
 114:   
 115:      }
 116:  }



We next create a Control that inherits from our abstract RequiredInput class.  For a simple example, we'll add a TextBox, again specifying the DesignerSerializationVisibility to DesignerSerializationVisibility.Content so that we will be able to access the properties of the TextBox.  We will also expose a public property "Text" to be able to easily grab the text value from the TextBox.

In CreateChildControls, we first call base.CreateChildControls so that our Label and RequiredFieldValidator are created by the RequiredInput base class.  Then we create the TextBox object and add it to the Control, give it an ID and then hookup the Label's AssociatedControlID to this ID.  This will render the Label as an actual <label> tag in the HTML and move the cursor to the TextBox when the label itself is clicked.

We also add the Validator to the Control and set the ControlToValidate property to the TextBox's ID and we set the Enabled property of the Validator to the Required value of the RequiredTextBox control.  This allows us to shut off validation of the TextBox if we don't need it.

In the Render method, write a <div> wrapper for the Label, Validator, and TextBox, adding a "class" attribute if the RequiredTextBox's CssClass has been set.  We then render out the contents of the Label, Validator and Textbox in the correct order based on the LabelLocation.

 

 

Step 3:  Using the Controls


To use these controls, you can build the server control .dll and add it as a reference to your web project, then register the control:

<%@ Register Assembly="RequiredInput" Namespace="OurCurrentFuture" TagPrefix="cc1" %>

.. and declare it in your code

<cc1:RequiredTextBox ID="rtbName" runat="server" Label-Text="Name" />

Notice the Property "Label-Text".  Since we used the DesignerSerializationVisibility attribute above, we can now access all of the Properties for the TextBox, Label, and Validator right from the .aspx page.  For example, to set the CSSClass of each, you could declare your control like this:

<cc1:RequiredTextBox ID="rtbName" runat="server"
            CssClass="control"
            TextBox-CssClass="input"
            Label-Text="Name"
            Label-CssClass="label"
            Validator-CssClass="error"
/>


Click here to download a .zip file containing all of the code in a Visual Studio 2008 solution file along with a demo web project showing how it can be used.

Got ideas on how to make this better?  Post a comment and let me know!


If you liked this post, please be sure to subscribe to my RSS Feed.


As a follow up to my last post about how to make a fist, I found a great article on GrappleArts.com about improving grip strength. Included are step-by-step exercises with photos for increasing wrist, thumb and finger strength. While most of the exercises do require some sort of equipment, it ranges from a bag of sand to run of the mill free weights, and nothing looks very difficult or expensive to obtain. The article is written by Rick Walker, who seems to have a good... grip... on the subject. 
If you liked this post, please be sure to subscribe to my RSS Feed.


Categories: Conditioning | Self Defense 
 

I've added a couple BlogEngine Extensions to this site and this post is mainly to test them out.

MP3 player:  Supreme Beings of Leisure - Never the same 


If you liked this post, please be sure to subscribe to my RSS Feed.


Categories:  
 

I can't quite call it a resolution, but I am going to try to write at least one entry in here per week.  I have a feeling that the topics wil shift more towards self defense and martial arts as it's easier for me to write them since I don't have to worry about formatting code and the like.

 

To that end...

 

How to make a proper fist

The fist is one of the most basic weapons your body has to offer.  Most non-martial artists think that just balling your hand up is good enough, but they couldn't be further from the truth. Punching something with an improper fist is not only not as effective, but can lead to serious injury - possibly even destroying one of your best weapons with your first strike.

 

There is a tutorial available on FightingArts.com that is excellent, but I disagree on one very important part - thumb placement.  The author states that thumb placement doesn't really matter, and mentions how different styles go about it differently.  For the purpose of this article, I'm talking about the basic fist from American Kempo.

 

To make a fist, start with an open hand.  Your fingers should be together.

 

 

Next, bend your fingers at the first and second knuckles until your fingertips are resting on the pads just below where your fingers connect to your palm. 

 

 

Continue to roll your fingers inward until your knuckles form a 90 degree angle.  I find that my fingertips naturally align on the "heart line" of my palm.

 

 

Tuck your thumb against the side of your index finger. 

    

 

Why does thumb placement matter? 

Let's take a look at the physiology of the hand.

 



(Image from Grey's Anatomy)

Notice the muscle groups of the thumb.  When you make a fist and bring the thumb underneath, you're stretching those muscles around the side of your hand.  While it would seem that this would make the fist stronger, it actually does the opposite.  When you bring the thumb alongside the fist, all of the muscles and tendons align together rather than those of your fingers going along the top of your fist and those of your thumb going around and underneath.

 

A simple way to prove this (and one of my favorite "martial arts parlor tricks") is to have someone make a fist with the thumb underneath.  Using one hand to brace the wrist and the other to push down on the top of the fist, you can easily "break" the wrist - causing it to bend.  If you have the person move the thumb to the side of the fist, it becomes much harder to do so.  This translates directly to how strong your fist will be when you actually hit a target with substance.  If your wrist rolls during a punch, chances are you're going to sprain it pretty badly and you could even cause permanent damage.

 

An added benefit is the time it takes in making a fist.  I tend to leave my hands open while fighting unless I'm actually throwing a punch.  That microsecond difference between bring the thumb around and tucking it to the side means that I can keep it relaxed longer, only tightening it on impact.  It also helps prevent getting caught on clothing as there is no point in which your thumb is separated from your fingers.

Do you agree?  Disagree?  Does you style use a totally different type of fist?  I'd love to hear about it in the comments.


If you liked this post, please be sure to subscribe to my RSS Feed.


Categories: Self Defense 
 
 

I know. It's been a while since I've written an entry.

After MS ASP.NET AJAX and the AJAX Control Toolkit came out, I lost interest in the control I had written. However, I saw this video on Digg (you can always see a list of what I've Dugg lately in the righthand column) and wanted to share.

Her name is Satoko Shinashi, her record is 24-1-2, and she is truly amazing. I would love to see her fight in person.. though I have a feeling it would be over quickly. I really wish more women were featured in professional MMA here in the US. Watch a bunch of her fights on YouTube


If you liked this post, please be sure to subscribe to my RSS Feed.


Categories:  
 
Finally.. after many modifications, the AJAX AutoComplete for ASP.NET 2.0 web user control is available for download.  This web control contains a text box. As you type in the box, suggestions fill in a drop down, very similar to Google Suggest. 

There are many configuration options, so if you are looking for a quick fix, you shouldn't have to get your hands too dirty.  On the other hand if you're looking for a base to build on, all of the C# and javascript code is included - hack away to your heart's content. If you make something cool, leave a comment and let me know about it. 

The styling for all of the components is done with CSS contained in an external file.  All you need to do is set the control's properties to the class names for each element.  There are other display options, optional features like AutoPostBack, case-sensitivity, server-side caching and other search options as well.  For more information on what you can do, read the documentation.

Or if you're one of those people who are more of a hands-on learner, you can play with the demo which is also included in the .zip file.

Download the Visual Studio 2005 Solution .zip file (18k)

I designed this control to be very easy to use, however it does assume you have a working knowledge of ASP.NET.  I will do my best to answer any questions, but the software is offered with no guarantees.


If you liked this post, please be sure to subscribe to my RSS Feed.



I've noticed over the past few days that I've been getting a lot of hits on the AJAX Autocomplete post I made, so I've decided to package up what I've done into a downloadable and reusable user control.  At the moment, I'm taking a lot of the options I had hardcoded (case sensitivity, whether it autocompletes based on "Starts with" or "Contains") and creating them as Parameters.

Check back soon for an update or better yet, subscribe to the RSS feed to know when it's been released.

EDIT:  It is now available - More Information

 


If you liked this post, please be sure to subscribe to my RSS Feed.


Edit: 4/12/06

I'm going to make this available as a download as soon as I have it cleaned up.  See here for more details.

Edit: 4/21/06: It is now available - More Information

Tonight, I was able to get my category AutoComplete feature working using AJAX in ASP.NET.  I have a query text box that fill the matching categories into a textbox as you type, similar in idea to Google Suggest.

Here's how it works..

As you type, the onKeyPress event is triggered, sending the query back to the server in the background.  On the first call of the page, it checks the Cache to see if the category list is already loaded.  If not, it goes out to the database and loads it into a Generic List object and then saves that object into Cache.  If it is located in Cache, it just grabs the Cache Item, casts it to List<string> and uses that.

Then I take what the user has typed so far and use List.FindAll() to find all matching values. Since it's coming out of memory most of the time, it's pretty fast.  There also aren't many categories, so even when it needs to go out to the database, it doesn't take too much time. Once it has all of the matching values, they are concatenated with commas and sent back to the client side.

The Javascript then takes that string, splits it along the commas and adds a new line to the textbox.


function fillAutoComplete(result, context) {
    fields=result.split(',');
    var txtAutoComplete = getObj('AutoComplete');
    txtAutoComplete.obj.value='';
    for (var i=0; i<fields.length; i++) {
        txtAutoComplete.obj.value += fields[i]+'\n';
   }
}

Currently, I have it just filling a textbox for test purposes, but eventually, it will be in a clickable dropdown.  The key to this is making it easy for the user to select a category of food to either add to their daily diet tracking or for the classification of custom foods.  This UI interface is a great blend of browsing and searching.  As you type, a search is performed which progressively limits the items you have to browse through.

It's coming along.. slowly, but surely.


If you liked this post, please be sure to subscribe to my RSS Feed.


I know I have been neglecting the self-defense aspect of this blog lately.  I'll try to keep it more balanced.  Today, I helped one of my fellow students test for his black belt.  I received mine about 2 and half years ago.  Unlike other dojos where testing is a formality where you perform a kata in front of a panel of judges, our test are hard.  Really hard.  3 Days Long Hard.

Unfortunately, I can't tell you more about it.  Our tests are closed door.  Nobody except the people testing and black belts are allowed into the test.  No parents, no spouses, no spectators.  Today I was an uke, which translates roughly as "human punching bag".  I attacked while my partner - who was the one testing for his black belt - performed the technique.

There were 3 other people testing and they all worked hard and they all did really well.  One point, we were free sparring 3 vs 1 on the testees.  Afterwards one of the other people testing came up to me and asked if I was a black belt from this school.  I told him that I was.  He asked if I had trained anywhere else and I said no and asked why he asked.

He told me it was because I didn't fight like anyone else he's fought against in our school.  Most people come in on you quickly, take a couple shots and then get out quickly.  Very common when you train sport karate or point fighting.  You get in, score your point and get out.  It's very controlled.  He said I came in like a truck.. there was no stopping, no jumping back out.  I came in hard and just kept coming, blocking when I needed to and striking every chance I could.

I laughed and explained to him that was because of my instuctor.  Within my school, my class has a certain reputation of being the people who like to fight.  The ones who don't mind getting banged up.  We train as if it were a real confrontation.  You don't want to punch an attacker a couple of times and stop.. you want to finish that fight at any cost, and that's the mindset we train with.

Though I study Kempo and there is limited grappling involved, in my class a lot of fights end up on the ground.  Why?  Because that's how a real fight goes.  There's nobody there to say, "Stop!" when someone trips or someone grabs you around the legs and takes you down.  We try to fight each other the way we would fight in the street because we all want to have faith that if we really did have to use this stuff that it would work.

Don't get me wrong, we're not trying to hurt each other.  The punches are still pulled a little and there's good sportsmanship all around.  But the strategy and the intensity is more like a real fight than a classroom.

They (and I'm using sweeping generalizations here, there are plenty of individuals who train the same way we do) don't have that mindset in a lot of the other classes.  My class is probably the smallest in the school because it takes a certain masochism to actually want to get hit.  In helping out this morning, I got two minor bloody noses and peeled a decent chunk of skin off of pinky toe via rug burn while getting thrown.  It happens.. you need to fight through it.  I'm used to it from being a little more rough and tumble and I know that if I get in a fight and someone gets a lucky shot that I can take it.

I find that many people who study in another class will come to ours because their instructor has told them to go to my instructor to "learn how to really fight".  And they'll come in with gorgeous form and perfect technique.. and get mauled by most of the people in our class.  That mindset is all they're missing.. but it doesn't take long to beat them into it.

 


If you liked this post, please be sure to subscribe to my RSS Feed.


Categories: Self Defense 
Finally.. I've made it through the nutrition database for TrueWeight and normalized all the data.  There's still some work to do on assigning the foods to categories.  I'm trying to decide between putting them in one-to-one heirarchical categories or using a one-to-many approach.  I'm leaning towards the latter.  Though it will make the back end a little messier, it will make the foods easier for the users to find and after all.. the main goal of this projects is to create something that is easy to use.

Next step will be creating the actual interface parts to select and add foods to the daily menu.

 


If you liked this post, please be sure to subscribe to my RSS Feed.


Categories: TrueWeight Project 

Subscribe

About the author

Wayne Hunt I am a web application developer and second degree black belt living in Providence, RI.

More about Me..

E-mail me Send mail

Other blogs

Dugg Sites

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2008

Sign in