Saturday, September 12, 2009

ASP.NET Composite Controls with Inner Controls

A Composite Control is simply a WebControl that contains one or more child controls, in this case the child controls are added in the mark up.
So lets starting with the main control.

First, in order to get VS support you have to add some attributes to the class, namely ToolboxData and DefaultProperty. This lets VS know how to parse the markup and tells VS to parse the MenuItem property for child controls making your class looks something like this:
   1: [DefaultProperty("MenuItems"), ParseChildren(true, "MenuItems")]
   2: [ToolboxData("<{0}:MenuControl runat=\"server\"></{0}:MenuControl>")]
   3: public class MenuControl : WebControl
Next you have to add the category attributes to the MenuItems property. When you do this you also need to set the DesignerSerializationVisibility and PersistenceMode options. This tells VS how to work with a collection of controls and you get something like this:
   1: [Category("Behavior"),Description("The item collection"), 
   2:     DesignerSerializationVisibility (DesignerSerializationVisibility.Content), 
   3:     PersistenceMode(PersistenceMode.InnerDefaultProperty)]
   4: public MenuItmeControls MenuItems {get; set;}
Next we override the Render method
   1: protected override void Render(HtmlTextWriter writer)
   2: {
   3:     writer.AddAttribute(HtmlTextWriterAttribute.Class, "Menu");
   4:     writer.RenderBeginTag(HtmlTextWriterTag.Div);
   5:     RenderContents(writer);
   6:     writer.RenderEndTag();
   7: }

This is basically creating a div tag, adding the cssclass “Menu” and writes the contents then closes the div tag, this step isn’t required, but if you don’t override it your control will be wrapped in a tag. I have no Idea way the span tag is the default, it just is. The next part is to render the contents, this is done by overriding the RenderContents method with something like this:
   1: protected override void RenderContents(HtmlTextWriter output)
   2: {
   3:     foreach (MenuItemControl item in MenuItems)
   4:     {
   5:         item.RenderControl(output);
   6:     }            
   7: }
Next you just loop though the MenuItmeControls stored in MenuItems and output them into the HtmlTextWriter, and the finished product looks like this:
   1: namespace UserControls
   2: {    
   3:     [DefaultProperty("MenuItems"), ParseChildren(true, "MenuItems")]
   4:     [ToolboxData("<{0}:MenuControl runat=\"server\"></{0}:MenuControl>")]
   5:     public class MenuControl : WebControl
   6:     {        
   7:         [Category("Behavior"),Description("The item collection"), 
   8:             DesignerSerializationVisibility (DesignerSerializationVisibility.Content), 
   9:             PersistenceMode(PersistenceMode.InnerDefaultProperty)]
  10:         public MenuItmeControls MenuItems {get; set;}
  11:  
  12:         protected override void Render(HtmlTextWriter writer)
  13:         {
  14:             writer.AddAttribute(HtmlTextWriterAttribute.Class, "Menu");
  15:             writer.RenderBeginTag(HtmlTextWriterTag.Div);
  16:             RenderContents(writer);
  17:             writer.RenderEndTag();
  18:         }
  19:        
  20:         protected override void RenderContents(HtmlTextWriter output)
  21:         {
  22:             foreach (MenuItemControl item in MenuItems)
  23:             {
  24:                 item.RenderControl(output);
  25:             }            
  26:         }
  27:     }
  28: }
To implement the control, you simply create a web page and add the control like this:
  1: <UC:MenuControl ID="menuControl1" runat="server" >
  2:    <MenuItems>
  3:       <UC:MenuItemControl id="myItem1" runat="server" Selected="true" LinkURL="http://google.com" Text="to Google"></UC:MenuItemControl>
  4:       <UC:MenuItemControl id="myItem2" runat="server" LinkURL="http://bing.com" Text="to Bing"></UC:MenuItemControl>
  5:       <UC:MenuItemControl id="myItem3" runat="server" LinkURL="http://yahoo.com" Text="to Yahoo"></UC:MenuItemControl>                               
  6:    </MenuItems>           
  7: </UC:MenuControl>

That's it, you can add as many menuItemControls as you would like. For the full source for this project go to Source Code Repository

Thursday, September 10, 2009

You, work, and the pursuit of happiness

Some of my acquaintance have recently, for one reason or anther, changed jobs, a couple of them have a new startup, one needed to find some sanity, etc. and this got me thinking about the last 10 years of my carrier, from places I loved to work at, some I didn’t care for, and some I couldn't work at again. Thinking of the unpleasant and out right bad jobs I’ve had I wondered was it the Job, my co-workers, or was it me?

In my life I have done some rather unpleasant jobs including: high school janitor, trash man, laborer, construction, QA engineer, etc. and no matter how unpleasant the job itself was, that wasn’t what made it a good or bad place to work, it was partly the work environment and partly my attitude. In "The Nomadic Developer” by Aaron Erickson (if you haven't read it I highly recommend it, if you don’t have time read it, listen to his interview on DotnetRocks episode 464 ) he talks about the 7 deadly firms and these are some really good examples of places you don’t want to be and everyone of them was a bad work environment. Company culture and team dynamics can make or break a work place.

If your work environment is negative it will affect you and your work, it’s hard to maintain a solid work ethic and energetic passion about what you do if your perpetually in fear of being reprimanded or worse loosening your job on the whim of some sadistic nut, to quote Yoda:

“Fear is the path to the dark side. Fear leads to anger. Anger leads to hate. Hate leads to suffering.”

So the next question is, are you helping or hurting your company culture? Are you the sadistic nut everyone fears? the kind mentor everyone looks up to? or Both? You and your Team mates attitude can make your company culture great to unbearable. So lets go over some of the things that help and hurt your team dynamics:

  1. Ego – Nothing hurts a team more then unchecked Egos, the I’m great and you suck attitude (even if it’s true) will destroy a team. That’s not to say having self confidence is bad or that you shouldn't have strongly held believes, but if your blind to everyone else's opinions you can’t function in a team. One, if not the, most important parts of team dynamics is the ability to see where the other people are coming from and why they think the way they do.
  2. Apathy – Nothing is harder to do then work with someone who is apathetic to their work. This shows up in several ways: the just tell me what to do and I’ll do it, the biggest problem here is, they probably wont do it the way you tell them to and you are just going to have to redo it yourself anyways; Next, this is just my day job, they only put in enough work to get by, they can’t be bothered to learn new things, or new skills and they slowly become dead weight; and last the good enough guy, we have all worked with this guy, any task you give him will end up being just slapped together without any other thought, they put as little effort into everything they do as they can and call it good. The worst part of all is a common problem with all of them, they are not contributing to the group thought process.
  3. Politics – Manipulating coworkers though office politics, even for the best of reasons, can be very detrimental to you, your team, your company, and depending on how far it goes could result in legal action. Even with the best of initiations playing politics at work is dangerous, remember Anakin Skywalker had the best intentions when he was seduced by the dark side and became Darth Vader, once you start it’s a very slippery slop and people start to suspect the reasons for your actions which leads to mistrust and it’s very hard to work with someone you can’t trust. The Other side is Politics for evil, a former co-worker who was, to be honest, fairly incompetent, would find someone on the team she felt she could demonize in order to advance her carrier, doing things like spreading rumors, making accusations, blowing faults and failing out of proportion, etc. in order to make her lack of ability less apparent. In this case it resulted in several people loosing there jobs and at least one lawsuit that I know off, and had the potential for a lot more.
  4. Bitterness – This is generally the after affect of one or more of the other items listed, someone get’s there ego hurt and have become apathetic to the point of being counter productive. Furthermore bitterness is contagious and can spread to the whole team destroying productivity.

Now that we have covered what can hurt you, how do you build up your team

  1. Open Mindedness -The ability and willingness to look at things from a different point of view, I hate to say it but your way isn't always right, and neither is mine. One of the things that made the Roman Empire so successful was their ability to learn from and adopt the technology of the lands they concurred. The same is true for software development, just because you have a more experienced developer on the team doesn't always mean they are always right, a junior developer may have fresh insight to a problem. The point is there is always room for different points of view, and by debating why one way is better then another your getting the team to think.
  2. Respect - Treating people with respect is one of the most important things you can do for team moral. I'm not saying you can't give each other good natured ribbing, in a way this can be a form of respect, you're showing each other you are comfortable interacting with them and having some good natured fun at each others expense. Just be sure it stays good natured and all parties involved are ok with it. If taken too far it becomes disrespectful and is detrimental to everyone involved. Finally, truth be told we have all worked with people we really have a hard time liking, respecting or just getting along with: an incompetent boss, the crazy conspiracy theorist, the suck-up co-worker, an office gossip, etc. If you can personally respect them or not is irrelevant they should always be treated with respect, if you don't you've started down the path to bitterness and/or apathy and your only hurting yourself.
  3. Dedication - This isn't just the willingness to put in the extra time to get something done, but to actually care about how something is done and the willingness to look for better ways to do it.

Something else to keep in mind is even if you are on a great team, it still might not be the right place for you. There are any number of reasons incompatibilities, it doesn't mean there is anything wrong with you or the team you're just incomparable and that's ok. A perfect example is if you have a very large skill set difference and the more advanced developer isn't able/interested in being a teacher/mentor, some people just don't have the interpersonal skills and if this person is having to spend all of their time trying to teach when they don't want to it can really be detrimental to their performance, and can lead to skill rot because they are no longer able to advance themselves and can loose some of their abilities because they never use them.

Finally, the most important thing to keep in mind is if you can't change where you work, then you need to change where you work. If you are doing everything right and your contributions don't affect anything, you need to find a place where what you do will change things, because if your not able to enact change, sooner or later your jobs is going to go away and you will have to find a new one, and it's much better to find one when it's on your terms and not because you have to.