CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Eric Wise

Business & .NET

April 2006 - Posts

  • Telerik, Atlas, and my Typeable DropDownList

    So I got to have some fun in the last 24 hours playing around with Atlas some more.  We're currently rebuilding the company's remote enrollment engine and we've decided that the April Atlas build is stable enough that we're going to go ahead and integrate it for a smoother client experience.

    In the initial "Postback" version we were using the Telerik Radcombo because it has some nice features like being able to type into the drop down box and filtering the list.  If you've never noticed by default the dropdownlist packaged with ASP .NET only allows for filtering by a single keypress.  As such, if you have a list with:

    Babbs, Bobby, Brutus

    You would have to hit the "b" key three times in order to select brutus rather than typing a more intuitve "br".  I find this highly annoying hence the use of the Telerik Control.  Much to my chagrin, however, I discovered that when wrapping the telerik control in an Atlas update panel it would promptly lose its skin/css after the asynch postback.  Searched the forums, found a solution that involved hardcoding the telerik javascript include but it didn't seem to work.

    Hey Scott Guthrie!  Can we get a prop on the dropdownlist control to allow typing instead of the default behavior?  =)

    In the meantime, I implemented my own with some help from Jonathan Cogley.  Note that it uses .NET 2.0 features for registering client script blocks etc.  I also stripped out any case sensitivity logic since I don't want it.  Being that it inherits from dropdownlist, it plays nice with Atlas, and seems to work just fine Firefox and IE.

    • So when you type "b" it will go and find the first "b" item.
    • When you type "r" it will move to the first "br" item.
    • If there is no "br" item it will reset the attribute and move to the first "r" item.

    Note that it's all case insensitive.  Without further ado, here's the control source:

        public class TypeableDropDownList : DropDownList

        {

            private static string functionName = "TypeableDropDownList_OnKeyPress";

     

            protected override void OnLoad(EventArgs e)

            {

                base.OnLoad(e);

                // define the client-side script

                StringBuilder script = new StringBuilder();

                script.Append("<script language=\"javascript\" type=\"text/javascript\"> \n");

                script.Append("  function " + functionName + "(ddl) \n");

                script.Append("  { \n");

                script.Append("    var undefined; \n");

                script.Append("    if (ddl.searchKeys == undefined) \n");

                script.Append("    { \n");

                script.Append("      ddl.searchKeys = ''; \n");

                script.Append("    } \n\n");

     

                script.Append("    var key = String.fromCharCode(window.event.keyCode); \n");

                script.Append("    ddl.searchKeys += key; \n\n");

     

                script.Append("    // convert to lowercase for compare \n");

                script.Append("    ddl.searchKeys = ddl.searchKeys.toLowerCase();\n\n");

     

                script.Append("    // loop options to find matches \n");

                script.Append("    var optionsLength = ddl.options.length; \n");

                script.Append("    for (var n=0; n < optionsLength; n++) \n");

                script.Append("    { \n");

                script.Append("      var itemText = ddl.optionsNo [N].text; \n");

                script.Append("      // option text should also be lower case \n");

                script.Append("      itemText = itemText.toLowerCase();\n");

                script.Append("      if (itemText.indexOf(ddl.searchKeys,0) == 0) \n");

                script.Append("      { \n");

                script.Append("        ddl.selectedIndex = n; \n");

                script.Append("        return false; // found it, returning false cancels Microsoft Default \n");

                script.Append("      } \n");

                script.Append("    } \n\n");

     

                script.Append("    // nothing was found, reset the search string and use the Microsoft Default \n");

                script.Append("    dropdownlist.searchKeys = key; \n");

                script.Append("    return true; \n");

                script.Append("  } \n");

                script.Append("</script>");

     

                if(!this.Page.ClientScript.IsClientScriptBlockRegistered(functionName))

                {

                    this.Page.ClientScript.RegisterClientScriptBlock(Type.GetType("System.String"), functionName, script.ToString());

                }

     

                this.Attributes.Add("OnKeyPress", "return " + functionName + "(this)");

            }

        }

     

  • There is no spoon

    Karl was weighing in today about his thoughts on how the productivity promises in ASP .NET 2.0 haven't quite panned out the way he wanted them too.  In one sense, I hear what he's saying, the 70% "code reduction" isn't there for enterprise users.  Nor was it intended to be.  The rad style development of dragging and dropping sql datasources and wiring things up was intended for a different scenario than Karl was into.

    One thing we can note from the history of programming and development is that over time, we have gotten more tools, not less to work with.  This is indicative of a problem set that is limited only by the human imagination.  As such, I would boldly suggest that no tool or language is ever going to be the end all across all problem domains.

    But I digress.  Where has ASP .NET 2.0 made me more productive?  Certainly not in the middle tier, but:

    • Superior xhtml compliance allows me to spend much less time futzing with the page markup.
    • Not an asp .net feature, but having visual studio not "help" you with your markup rearranging it like it used to ensures my markup is readable and thus easier to maintain.
    • I've spent some time of late with the object datasource... it's swanky, I like it... but I like the two line databinding code in the code behind better because I feel that as a developer, and like many developers, I tend to look at the codebehind first, and using page controls for datasources tends to hide the fact that they exist.  (karl- you did forget to mention that even though your 2 line codebehind is shorter there, you have to manually create all the columns in your grid rather than selecting them from a list.  I think you actually lose there *shrug*).

    Like Karl, I also have a "membership" provider that I already coded back in the day.  I've thought about porting it to the new version but I'm unconvinced as to the value since for the internal apps we don't email reset passwords or anything like that.  I'll probably end up doing it someday when I'm bored and have time, but it's not a high priority.

    Master Pages are a beautiful, wonderful productivity enhancement.  Don't believe me?  Remember the old days having to put user controls on every page for consistant layouts?  Ever have to add or remove one of those and have to go through every page stripping or adding it?  'nuff said.  The kerfuffle I've had with master pages has been limited to figuring out the best way to pass events around to the page content and master page content, but most of that is simply due to my inexperience with the master page concept and that I absolutely hate the way c# does events.  (My old position was all VB .NET and I feel like the VB way for events is way more intuitive than the c# equivalent)

    As other posters on Karls thread picked at visual studio, refactoring problems etc I tend to think that's a completely separate issue than how ASP .NET 2.0 works.  The compilation model tripped me up the first few times I played with it but it has been recognized and improved since then. 

    In the end, I have to credit CodeSmith as the biggest bang for my buck productivity enhancer in the business and data layers.  With the xhtml compliance and improved server controls, I spend much less time worrying about difference in browsers (it was painful in the 1.1 days achieving compliance across multiple browsers).

    Atlas I have played with the march CTP and I must say that before atlas, I used the Telerik callback control with pretty good success but Atlas blows it away.  I basically created a form with add/update/delete for addresses in the traditional postback methods.  Installed Atlas, watched Scott Guthrie's easy and informative video slapped a few lines of markup in and whammo, I had a whole page running in AJAX mode.  It was sweeeeeet.  I wouldn't call Atlas a productivity enhancer persay, since it's more work than using traditional postbacks, but from a user experience perspective it makes a leap over the old school style.

  • What does 10 lines give you anyway?

    While I agree with 95% of Jeffrey's post I have to throw down the gauntlet on the magic number of 10 lines in his suggestion.  Just as "magic numbers" are rather undesirable in code, the concept that a method should be constrained by a number of lines is undesirable as well.

    <rant>For me, this brings back memories of writing assignments in school where the teacher would insist that you write 1500 words.  What if you could elegantly cover the topic in 1000?  What made 1500 so damn special anyways?</rant>

    Anyways, I digress.  What I think should be said in place of the 10 lines concept is that wherever possible, a method call should be a complete thought / task.  Most tasks can be divided into subtasks which are thoughts on their own.

    The thing you really have to watch out for though (and the thing that prompted this post) is "code hop".  Code hop is when someone takes the 10 lines concept and goes way too far with it.  If I have to jump into more than 4 files just to follow a method call through the code, it's almost as bad as having a method of 60 lines.  At least with the 60 line method I can easily see the flow and steps that are being taken without having to jump around.  The downfall of the 60 line method is that the steps are not broken out to be reusable.

    So that's really the distinction I want people to make.  Go for simplicity and readability first.  Splitting out everything all over the place isn't simple or readable, nor is dumping everything into a super method.  Organization of code is somewhat of an art, and is another one of those things that coders can really benefit from exploring the code of others. 

    Bottom line if you're walking through my code, if something isn't meant to be reused, I tend to have a longer method to keep complete thoughts together.  I can always pull out chunks of code refactoring to make it reusable if the need arises.  I also don't mix major tasks, data retrieval is not mixed with business logic, etc.  But those are "thoughts" as described above.

    Fun semantic argument either way.  ;)

  • I'll see you at TechEd

    The title says it all.

  • Offtopic :: New Family Member

    Pretty damn cute if you ask me.  Though I'm not sure what my 1 yr old son thinks of the whole scenario.  He spent most of the weekend just following the puppy around.

     

  • I'm with Rocky

    While I refuse to get into the holy war that is going on between TDD enthusiasts and Rocky, I must say that I found this post pretty much summed up everything I have to say on the TDD front.  Unit tests by developers are definitely not a replacement for a QA team.  Where I do employ tests most often is in tricky parts of business logic, complex calculations, etc.

    The CRC method is the method I use for design.  It's straightforward, clean, and easy.  I would say the CRC link in his post is the hidden gem of the whole debate, more developers should use it.

More Posts