My jQuery Primer

So you have been reading about jQuery and want to dive in and try some? I recently attended the MSDN Dev Conference in Detroit where jQuery integration and client-side programming were very hot topics. With Microsoft’s acceptance of the open source library, I figured I would give it a try. This is what I have learned so far. Before I can show you what you can do with jQuery, I think I should probably show you how to get a reference to jQuery into your code. In ASP.NET you can add your reference directly to your Script Manager

<asp:scriptmanager id="pageScriptManager" runat="server">
<scripts>
<asp:scriptreference path="/client/jquery-1.3.1.min.js" />
</scripts>
</asp:scriptmanager>

What does jQuery have to offer? First and foremost, jQuery has given me power over the Document Object Model (DOM)! jQuery Selectors are the greatest thing since sliced bread, no lie. Being able to EASILY find an object or group of objects in the DOM by ID, CSS Class, or by HTML Tag is something web developers have long needed. To select an object from the DOM by ID would look like this:

$('#ID_Goes_Here')

To select an object from the DOM by CSS Class would look like this:

$('.CSS_Class_Name_Goes_Here')

To select an object from the DOM by HTML Tag would look like this:

$('<tag_goes_here>')

With jQuery Selectors being so simple, it allows the developer to easily select an object or a group of objects. Now that we can select objects, what can we do with them? This is where the power of Selectors really builds into what else you can do. In a web application, round trips to the server to manage UI is wasteful. I avoid JavaScript like the plague because it’s a pain in the ass. jQuery makes client-side UI management feel like climbing the rope in gym class. For example, if I have a label that I want to be rendered but not visible I could create the label.

<asp:label id="Label4" runat="server" cssclass="myLabel" text="This is " />

And later on in jQuery I can hide it like this.

$('#Label4').css('display', 'none');

It’s nice to be able to easily select an object and modify it, but what if you have a whole group of items you want to modify? With jQuery, you can EASILY loop through a collection of objects. In this example I have a group of labels.

<asp:label id="Label1" runat="server" cssclass="myLabel" text="This is " />
<asp:label id="Label2" runat="server" cssclass="myLabel" text="This is " />
<asp:label id="Label3" runat="server" cssclass="myLabel" text="This is " />
<asp:label id="Label4" runat="server" cssclass="myLabel" text="This is " />

Now I want to update the text of each label to include its ID. I am going to loop through each object in the DOM with a CSS Class of .myLabel.

$('.myLabel').each(function() { $(this).append(this.id); });

What the jQuery code above does is execute a function that will append the object’s ID to its text value. Notice the Selector inside the function $(this). The syntax is used to find the loop’s current object in the DOM. I do a lot of web work where I create controls on the fly. For my last example, I just wanted to show a way to quickly insert some HTML into a container object. I will start with a Panel AKA a DIV.

<asp:panel id="Panel1" runat="server" />

Now I am going to use jQuery to select my DIV and add some HTML to it.

$("#Panel1").html("<ul><li>Item One</li><li>Item 2</li></ul>");

Now I have shown you some snippets here and there, let me show you what my page actually looks like.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
	<title>jQuery Examples</title>
	<link href="/style/jQuery.css" rel="Stylesheet" type="text/css" />

	<script type="text/javascript">  function pageLoad() { $('.myLabel').each(function() { $(this).append(this.id); }); $('.myLabel').css('color', '#FFFFFF').css('font-size', '30px'); $('#Label4').css('display', 'none'); $("#Panel1").html("<ul><li>Item One</li><li>Item 2</li></ul>"); } </script>

</head>
<body>
	<form id=	<form id="pageForm" runat="server">
	<asp:scriptmanager id="pageScriptManager" runat="server">  <scripts>  <asp:scriptreference path="/client/jquery-1.3.1.min.js" />  </scripts>  </asp:scriptmanager>
	<asp:label id="Label1" runat="server" cssclass="myLabel" text="This is " />
	<br />
	<asp:label id="Label2" runat="server" cssclass="myLabel" text="This is " />
	<br />
	<asp:label id="Label3" runat="server" cssclass="myLabel" text="This is " />
	<br />
	<asp:label id="Label4" runat="server" cssclass="myLabel" text="This is " />
	<br />
	<asp:panel id="Panel1" runat="server" />
	<br />
	</form>
</body>
</html>

Links
jQuery: http://www.jQuery.com/
Object Model: http://en.wikipedhttp://en.wikipedia.org/wiki/Document_Object_Model

Javascript Anonymous Methods and How they help Ajax WebMethod

Ok so here’s what you’re trying to do:

You have a button and when it’s pressed you want to have it fill a drop down list without a postback. So your first thoughts are, “I like Mentos” followed by, “WebMethod” since you of course read this super awesome post. Now it might look like this:

        function GetUserList()
        {
            PageMethods.GetUserList(OnGetUserListComplete);
        }

        function OnGetUserListComplete(result)
        {
            var dropdownList = $get('dropdownListID');
            for (var i = 0; i < result.length; i++)
            {
                var item;
                item = document.createElement("option");
                item.text = result[i].UserName;
                item.value = result[i].UserID;
                dropdownList.options.add(item);
            }
        }

And GetUserList would be called on click. Fine and dandy, but this sort of bad since you’re hardcoding the id of the control. Meh. You look back at the method and see that there just isn’t a way to pass in a name, and if you didn’t you would be sooooo wrong it hurts. Shame on you. Good thing I’m here. The way you’re going to do this is to use an anonymous method. You see, as it is the PageMethod call needs a method to call post completion and that’s all it takes in. (Well not completely true, it can take in parameters for the server side method, but that’s not the point.) So you have to find a way for that PageMethod to call the method after completion AND make sure it has the list name with it.

        function GetUserList(dropdownList)
        {
            PageMethods.GetUserList(function(result) {
                 OnGetUserListComplete(result, dropdownList); });
        }

        function OnGetUserListComplete(result, dropdownList)
        {
            for (var i = 0; i < result.length; i++)
            {
                var item;
                item = document.createElement("option");
                item.text = result[i].UserName;
                item.value = result[i].UserID;
                dropdownList.options.add(item);
            }
        }

Ooo pretty tricky huh?

        PageMethods.GetUserList(function(result) {
                 OnGetUserListComplete(result, dropdownList); });

See what I did there, I created an anonymous method to be called on completion and in turn it calls the original (Though modified) OnGetUserListComplete method now. And you thought javascript sucked.

Call Server Side methods With Javascript in ASP.Net… Yeah Ajax

So I’ve been looking for something to match the simplicity of the old Ajax.dll WebMethods (The ability to asychronously call a method on a class from javascript) since the project was abandoned by the owner. A lot of what I saw before involved WebServices which wasn’t horrible, but I wanted Ajax.WebMethods. Come to find out, this simplicity exists in 3.5.

So let’s say I want to click on a div and have it’s innerHTML be filled with some string. Sounds like a completely viable situation for any money making business… Anyways, I could do some kind of post back and fill it, or I could use an update panel (Uhg) or I could use a Web Service or I could just bang my head on the desk and get the same level of satisfaction. But then came 3.5 and something wonderful. Take this page:

    public partial class Test : System.Web.UI.Page
    {
        [System.Web.Services.WebMethod]
        [System.Web.Script.Services.ScriptMethod]
        public static String GiveMeString()
        {
            return "hi";
        }
    }

See somethig weird? Yeah that’s the magic of the class file. All I need is:

  • A Static Method
  • The WebMethod Attribute
  • The ScriptMethod attribute
  • Optionally something to return, but for this example it’s not optional just like Burt Renold’s mustache

And now the page file is ready, but what about the markup? Well, that’s next, so glad you asked. First the javascript:

        function ShowString()
        {
            var test = $get('ShowThings');
            PageMethods.GiveMeString(OnGiveMeStringComplete);
        }

        function OnGiveMeStringComplete(result)
        {
            var test = $get('ShowThings');
            test.innerHTML = result;
        }

First method is the method to call. The PageMethods object will allow the use of the class method that was created. The parameter being sent in is actually the method needing to be called when the server side call is complete. With that in mind, guess what the second method is… No, not ice cream. It’s the method called when the server call is compete. As you can see, I am simply changing the innerHTML of a div.

    <form id="form1" runat="server">
        <asp:ScriptManager ID="smMain" runat="server" EnablePageMethods="true" />
        <div id="ShowThings" style="background-color:Yellow;height:20px;width:20px;"
          onclick="ShowString()"></div>
    </form>

And there you have the markup. ScriptManager is a must in this case, but that’s pretty standard when dealing with Ajax in asp.net. The only other thing of note is the method call on the div’s onClick. Beyond that, it’s ready to go. And if you were to make this example yourself and click on the div, you will get a ‘hi’ string in it on the first click. Amazing.

Use Javascript and an HttpHandler to Load an Image from a Database

This might be part of another ongoing series, but the for this post, right here, RIGHT NOW, I am going to show are really simple but fun (??) way to change an image’s… eh image from a database stored image using Javascript and an .ashx file. And when I say simple, I mean it took me longer to get test code going than it did to make this work.

First you need a handler (If you don’t what this is for, well for this example it allows you to create a non existant url for an image loaded from the database.) which is aptly named Generic Handler when you do the usual Add New Item. Amazing. You should get something like this in the class file:

    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class SomeImage: IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/plain";
            context.Response.Write("Hello World");
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }

Yeah you like that don’t you? Yeah you do.

So now we have something to display the image right? Well that’s pretty easy too. For me, I have an UserImage class I created with Linq to Sql to mimic my UserImage table. I’m cool like that. I then created a method to return the image bytes based on the ID sent in. That part is up to you how to handle. The main thing you need is to get the image bytes somehow. With that in mind, here is what the class file looks like now:

    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class ShowImage : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            Int32 imageID;
            Byte[] imageBytes;

            imageID = Convert.ToInt32(context.Request.QueryString["ImageID"]);
            imageBytes = UserImage.GetImageBytesById(imageID);
            context.Response.ContentType = "image/jpeg";
            context.Response.Cache.SetCacheability(HttpCacheability.Public);
            context.Response.BufferOutput = false;
            context.Response.OutputStream.Write(imageBytes, 0, imageBytes.Length);
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }

As you can see, the query string has an id being sent in and I’m retrieving it. From there I get the image bytes, tell the context what it is, how to handle the cache, and sending the bytes out. What you can’t see right now is that somewhere I have something that looks like this:

   <image src="SomeImage.ashx?ImageID=1" />

When that url is read, it will send it off to the handler to get and display the image. (Not taking caching into account mnd you)

Now I know what you’re thinking right now, “I’m bored” which I understand but you’re also thinking, “Where’s the f@&#ing javascript?”. Well my vulgar friend, it’s on the way.

<head runat="server" >
        <script type="text/javascript" language="javascript">
        function TestThis(name, imageID)
        {
            var test = document.getElementById(name);
            test.src = 'ShowImage.ashx?imageID=' + imageID;
        }
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <div style="background-color:Gray;height:20px;width:20px;" onclick="TestThis('hi', 1);"> </div>
        <div style="background-color:Red;height:20px;width:20px;" onclick="TestThis('hi', 2);" > </div>
        <div style="background-color:Blue;height:20px;width:20px;" onclick="TestThis('hi', 3);"> </div>
        <br />
        <img src="" id="hi" name="hi" />
    </div>
    </form>
</body>

So now every time one of the three divs is “clicked”, the image is changed depending on the image id sent in using the “url” of the handler you created. Much like sending information to another page, you send the id to the handler so it can display the correct image.

I realize this isn’t the best of examples but it’s a push in the right direction. Maybe next time you want something, you won’t swear at me.

Ajax Control Library: Autocomplete Control to Scriptcontrol

[Part One] [Part Two] [Part Three] [Part Four] [Part Five]

Ok so in part four I showed you how to create a webcontrol from the AutoComplete control, so now it’s time to take the first four lessons and combine them. Now it’s time to have an autocomplete script control. The first part is really simple, just like before you have to:

  • Inherit from ScriptControl
  • Override the GetScriptDescriptors and GetScriptReferences methods
  • Create the .js file
  • Make the .js file an embedded resource
  • Update the assemblyinfo file in the Properties folder
  • Add the minimal needed javascript

So it will look something like this:

public class AutocompleteScriptControl : ScriptControl, INamingContainer
{
  private AutoCompleteExtender autoComplete;
  private TextBox textboxTarget;

  protected override void CreateChildControls()
  {
    base.CreateChildControls();

    autoComplete = new AutoCompleteExtender();
    autoComplete.ID = "autoCompleteMain";

    textboxTarget = new TextBox();
    textboxTarget.ID = "textboxTarget";

    Controls.Add(textboxTarget);
    Controls.Add(autoComplete);
  }

  protected override void OnPreRender(EventArgs e)
  {
    base.OnPreRender(e);
    autoComplete.TargetControlID = textboxTarget.ID;
  }

  protected override IEnumerable<ScriptDescriptor> GetScriptDescriptors()
  {
    ScriptControlDescriptor desc =
      new ScriptControlDescriptor("Test.Examples.Client.AutocompleteScriptControl", ClientID);
    desc.AddProperty("textboxTargetID", textboxTarget.ClientID);
    desc.AddProperty("autocompleteID", autoComplete.ClientID);

    return new ScriptDescriptor[] { desc };
  }

  protected override IEnumerable<ScriptDescriptor> GetScriptReferences()
  {
    return new [] { new ScriptReference
      ("Test.Examples.AutoCompleteExample.AutocompleteScriptControl.js", "Test.Examples") };
  }

}

And the script file:

if (Type)
{
    Type.registerNamespace("Test.Examples.Client");
}

Test.Examples.Client.AutocompleteScriptControl = function(element)
{
    Test.Examples.Client.AutocompleteScriptControl.initializeBase(this, [element]);

    this._autocompleteID = "";
    this._textboxTargetID = "";

    this._autoComplete = null;
    this._textboxTarget = null;
}

Test.Examples.Client.AutocompleteScriptControl.prototype =
{
    get_autocompleteID: function()
    {
        return this._autocompleteID;
    },

    set_autocompleteID: function(value)
    {
        this._autocompleteID = value;
    },

    get_textboxTargetID: function()
    {
        return this._textboxTargetID;
    },

    set_textboxTargetID: function(value)
    {
        this._textboxTargetID = value;
    },

    initialize: function()
    {
        this._autoComplete = $get(this._autocompleteID);
        this._textboxTarget = $get(this._textboxTargetID);

        Test.Examples.Client.AutocompleteScriptControl.callBaseMethod(this, 'initialize');
    },

    dispose: function()
    {
        Test.Examples.Client.AutocompleteScriptControl.callBaseMethod(this, 'dispose');
    }
}

/***********************************/

Test.Examples.Client.AutocompleteScriptControl.registerClass
    ('Test.Examples.Client.AutocompleteScriptControl', Sys.UI.Control);

And now this is the bare minimum needed to get this done.

Dynamic Markup Property Collection for a WebControl

I wasn’t exactly sure how to write this title as it’s not easy to explain in a short sentence, however I can say that I am completely embarrassed by the result and may have to consider hiring a title consultant. However, for now it will have to do.

Ok so what is this about? Well let’s say you have the control from the last example and you don’t want a list of controls in the markup, but maybe you want a list of strings set in the markup. (Say for a list of settings) Or even better, let’s say you have controls already on the page but you want our ParentControl (Yes I said “our” but no I’m not proposing… yet) to do something with those controls. Say we want to have the ParentControl to assign some javascript to certain buttons on the page. Ok yeah, kind of dumb but that’s the example I made. I supposed you could think of it like this: You want a validation control to validate multiple controls but you want to give it the names of the controls in the markup. Anyways, let’s stick with the example I already have.

First off you’ll need to create a new class, something that you want to hold the information in. (Although truth be told I could do something way easier and just use a list of strings, but this should prove more interesting) Here’s the one I have:

  namespace Test.Frontend.ControlInControl
  {
    public class ChildControlDefinition
    {
        public String ControlName { get; set; }
    }
  }

Pretty sweet? Eh? Eh? No? Ok. So now we have a class, and that’s like wow. Now with the same attributes from the old example, build the WebControl:

    [ParseChildren(true)]
    [PersistChildren(false)]
    public partial class ParentControl : UserControl
    {
        public List<ChildControlDefinition> NamedControls { get; set; }
    }

Holy smokes, that just got way complicated compared to the last example. I added a whole new property NamedControls that is a list of the ChildControlDefinition class we created. Now you might notice that the AddedControls property from the old example isn’t there anymore. I just removed it to simplify this one.

And then there’s the markup:

    <asp:Button ID="mainButton" runat="server" />
    <uc1:ParentControl ID="ParentControl1" runat="server" >
        <NamedControls>
            <examples:ChildControlDefinition ControlName="mainButton" />
        </NamedControls>
    </uc1:ParentControl>

Now you might notice two things here:

1) There is a mark up section named “NamedControls” just like the collection. Can you guess why?

2) examples:ChildControlDefinition : This is the class type name and the TagPrefix for where the class is. For this to work, you have to register the assembly the class is in EVEN IF the class is in the web application assembly. So it would look like this:

<%@ Register Assembly="Test.Frontend" Namespace="Test.Frontend.ControlInControl" TagPrefix="examples" %>

Now what does this do for anyone? Possibly it prevents you from dying a little inside but it also allows you to find those controls within the usercontrol… Ah buh? Don’t worry, I’ll show you!

    [ParseChildren(true)]
    [PersistChildren(false)]
    public partial class ParentControl : UserControl
    {
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            NamedControls.ForEach(ConnectButtonToClick);
        }

        private void ConnectButtonToClick(ChildControlDefinition control)
        {
            Button foundControl;

            foundControl = Page.FindControl(control.ControlName) as Button;

            if (foundControl != null)
            {
                foundControl.OnClientClick = "alert('clicked'); return false;";
            }
        }

        public List<ChildControlDefinition> NamedControls { get; set; }
    }

See what I did there? SOMETHING COMPLETELY USELESS and yes you too can now have that power. However, there might be something worth taking home from that example. From the list of ChildControlDefinition I was able to get the control name that I wanted to attach the worthless alert script to and attach it. How was that done? Well I just iterated through the ChildControlDefinition list, used the Page.FindControl method to find the control, and then set the OnClientClick method.

Now this example is pretty stupid but I hope you can see the overall value of this. One would be a paging controller that has a list of paging control names that it iterated through and sets various events so they can all work in harmony like one great big continuation of the Hands Across America utopia that just didn’t seem to make it.

Now to spin it Nintendo User Manual Style:

Think you are bad enough for Dynamic Controls? Take grab of the power within and dare to conquer! Take a chance, the world can be your for the taking! Dynamic is waiting…

Add Controls to Control in ASP.Net (With Less Pulp)

So this should be a fairly easy showing and you’ll be on your way quickly. Hell most likely you won’t finish this sentence before going somewhere else. BUT for those who brave this post, you will be rewarded… I hope.

So here’s the problem, you have a UserControl/WebControl/ExtenderControl/ScriptControl/… (Seriously?) that you want to be able to add controls to in the markup like thus:

<SomeControl>
  <ControlList>
    <asp:Label />
    <asp:Label />
  </ControlList>
</SomeControl>

As you see here, the idea is that SomeControl actually can dynamically house controls based on the markup. Seems like this should be hard, but in reality it’s pretty simple. First start with creating a user control, which I hope you know how to do. (I’m calling it ParentControl) Second open up the class file and let’s add some stuff.

    [ParseChildren(true)]
    [PersistChildren(false)]
    public partial class ParentControl : UserControl
    {
        public ParentControl()
        {
            addedControls = new List<WebControl>();
        }

        private List<WebControl> addedControls;

        public List<WebControl> AddedControls
        {
            get
            {
                return addedControls;
            }
        }
    }

And honestly, that’s the code needed but I’ll give a literary once over to make sure things are clear.

So first off you have to add a list of controls to the eh… control and create a property that is used to access it and this can actually be done verbosely:

        //Field
        private List<WebControl> addedControls;

        //Instantiation on constructor
        public ParentControl()
        {
            addedControls = new List<WebControl>();
        }

        //Property to access
        public List<WebControl> AddedControls
        {
            get
            {
                return addedControls;
            }
        }

OR the easy way (Which is not what the original example showed:

        public List<WebControl>AddedControls { get; set; }

As you can see, the 2.0 auto property syntax will actually work for this. So if you like that, you can save yourself some typing.

Ok so now we have a property, and field if you choose, to handle this. Sounds way too easy right? Well the magic is in the attributes:

    [ParseChildren(true)]
    [PersistChildren(false)]
    public partial class ParentControl : UserControl

And you’re all set. Now the markup:

    <userControl:ParentControl ID="ParentControl1" runat="server" >
        <AddedControls>
            <asp:Label ID="labelHi" runat="server" />
        </AddedControls>
    </userControl:ParentControl>

Still waiting for this to get complicated? Well you’re going to waiting for a long time because that’s it. When page load comes around will now have a list with the label in it. Pretty nice huh?

Return False from a ScriptControl method and why I hate Firefox…

I have to admit that it might be IE that is wrong, but I don’t know. That and I do kind of hate Firefox so I’ll stand by the title anyhow.

This is a little off the current beaten path, but does deal with the current ScriptControl theme so I thought I’d put it in here.

Here’s the problem: You have a script control, a button, and want to have the person confirm before it’s allowed to postback. Easy right? If this were the non script control way you would do this:

Javascript:

    function ReturnFalse()
    {
      var confirmed = confirm('Is there anyone more awesomer that Sean?');
      return confirmed;
    }

Markup:

  <asp:Button ID="whoCares" runat="server" OnClientClick="return ReturnFalse();" >

Class Stuff:

  whoCares.Click += whoCares_Click;
  ...
  private void whoCares_Click(object sender, EventArgs e)
  {
    throw new NotImplementedException();
  }

Basically what I’ve done is made it so that if it doesn’t return false, an exception is thrown. Easy test. Works in both browsers right? Brilliant.

Now for the script control:

  handleLnkDeleteButtonClick: function(e)
  {
      var confirmed = confirm('Is there anyone more awesomer that Sean?');
      return confirmed;
  },

 initialize: function()
 {
    this._lnkDeleteButton = $get(this._lnkDeleteButtonID);
    this._lnkDeleteButton.idpicker = this;

    //HOOK BEGINS HERE
    this._lnkDeleteButtonClick = Function.createDelegate(this, this.handleLnkDeleteButtonClick);
    $addHandler(this._lnkDeleteButton, "click", this._lnkDeleteButtonClick);
    //END HOOK HERE

    NDI.WebControls.Client.PersonalMessageTypePicker.callBaseMethod(this, 'initialize');
},

Now that looks ok right? The method pops up the confirmation button alert dialogue thingy and returns the answer but guess what, you’re wrong. So wrong. In IE this works but in Firefox, sorry no deal. Firefox will ignore anything returned if the “return” keyword is not in the markup. Well from here there’s no real markup so how the hell would I do that? Well yes Virginia there is a Santa Clause and he lives in e.preventDefault();

It’s actually really simple, one small change in the handling method. You replace return X with e.preventDefault();

  handleLnkDeleteButtonClick: function(e)
  {
    var confirmed = confirm('This will delete the currery Message category
      and move all messages to the Oprhan cataegory.  Allow?');
    if (!confirmed)
    {
        e.preventDefault();
    }
  },

And now it works. Yes you can thank me with large donations of money or cheese.

Make an Autocomplete Control a Webcontrol

[Part One] [Part Two] [Part Three] [Part Four] [Part Five]

So in the last post I showed the easy way to use the Toolkit Autocomplete control, but it might have left you with some questions like: Do I have to keep adding a textbox everytime I want an autocomplete control? Is there an easy way to make a composite control? Is this guy an idiot?

The easy answer is: yes.

Now I’m not a huge fan of making web project controls (.ascx) unless there is heavy style formatting. For the most part if its going to be usable somewhere else and it is fairly simple to represent codewise, I’ll put it in a class library as a WebControl or ScriptControl. So how is this done with the autocomplete?

For my examples, I’ll be using the same root namespace as the Script Control examples, namely Test.Examples.AutoCompleteExample. Now that I have a wonderful folder created I’m going to go ahead and create a WebControl Class named AutoCompleteControl.

Now when I create this new control there are some things I will need:
-Has to inherit from at least WebControl (ScriptControl example I will do later)
-Has to have a textbox (The autocomplete needs a target control)
-I would strongly suggest a certain amount of properties to be exposed, basically reflecting the properties on the autocomplete
-I added the implementing of ITextControl mainly to relfect a .Text property but that isn’t really needed. I just found this useful if you end up treating this control like a textbox for say validation purposes.

    public class AutoCompleteControl : WebControl, INamingContainer
    {
        private AutoCompleteExtender autoComplete;
        private TextBox textboxTarget;

        protected override void CreateChildControls()
        {
            base.CreateChildControls();

            autoComplete = new AutoCompleteExtender();
            autoComplete.ID = "autoCompleteMain";

            textboxTarget = new TextBox();
            textboxTarget.ID = "textboxTarget";

            Controls.Add(textboxTarget);
            Controls.Add(autoComplete);
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            autoComplete.TargetControlID = textboxTarget.ID;

            autoComplete.CompletionInterval = 5000;
            autoComplete.EnableCaching = EnableCaching;
            autoComplete.CompletionSetCount = CompletionSetCount;
            autoComplete.MinimumPrefixLength = MinimumPrefixLength;
            autoComplete.OnClientItemSelected = OnClientItemSelected;
            autoComplete.ServiceMethod = ServiceMethod;
            autoComplete.ServicePath = ServicePath;
        }

        public Int32 CompletionSetCount { get; set; }

        public Boolean EnableCaching { get; set; }

        public Int32 MinimumPrefixLength { get; set; }

        public String OnClientItemSelected { get; set; }

        public String ServiceMethod { get; set; }

        public String ServicePath { get; set; }

        public String Text
        {
            get
            {
                EnsureChildControls();
                return textboxTarget.Text;
            }
            set
            {
                EnsureChildControls();
                textboxTarget.Text = value;
            }
        }
    }

Well hell that was easy, wasn’t it? All I had to do is create the class, add the textbox and autocomplete as controls, and set a few properties. Voila, we now have a working autocomplete control. Now if you had read the last post on this (Page 3) then you might have noticed this new property:

CompletionInterval

What is that? Well apparently it deals with the amount of time a particular item is highlighted when hovering over it. Found this out the other day. SURPRISE!!

Couple of points from this:

Why?
– Well if nothing else, you now have a compostite control to use. The markup will supply the service location and the method to use, everything else is taken care of with this control.

– On top of that, this can now be snug in a class library (assembly) for reuse thus removing it’s need to be recopied everytime you need it in another web project.

– You can now inherit from this control to add fucntionality if you need.

– You can now convert this to a script control in order to access javascript events and other fun things.

So as you can see, this is a pretty good way to go.

Something else of note is the CreateChildControls/EnsureChildControls situation. CreateChildControls is a overridable method that is used to make sure that the controls themselves are created and handled. The nice thing about this is that you won’t run into the timing issues you might if you try to initialize controls in other methods like OnInit. Also, it allows you the use of the EnsureChildControls method. When this method is called, the CreateChildControls method is either called or not depending if it’s already been run. EnsureChildControls basically asks if CreateChildControls has been run. If it has then it doesn’t call it again, if it hasn’t then the method is called to create the controls. So as you can see, this makes it easy to guarantee that the controls have been created in order to access them. This becomes important with properties that are tied to controls as there is no guarantee that when a property is accessed the controls aren’t null. Kind of nice, huh?

Also you might have noticed that I set all the control properties that were “attached” to the autocomplete in prerender. Usually for safety, I don’t both setting any outward facing properties like that until prerender so that I know I have the latest and greatest values.

Just incase you needed the markup example:

<%@ Register Assembly="Test.Examples"
  Namespace="Test.Examples.AutoCompleteExample" TagPrefix="test" %>

<test:AutoCompleteControl ID="autoCompleteTest" runat="server"
  ServicePath="~/Service/AutocompleteWebControl.svc" ServiceMethod="GetUserNameList"
  CompletionSetCount="10" MinimumPrefixLength="1" />

HOLY SMOKES NO NEED FOR TEXTBOXES!!11

  using System.Web.UI;
  using System.Web.UI.WebControls;
  using AjaxControlToolkit;

Ajax Control Toolkit Autocomplete – How to use… simple example.

[Part One] [Part Two] [Part Three] [Part Four] [Part Five]

So in my journey to create an autocomplete control, I had it working except something really screwy with the stylesheet and how to make it look… oh I don’t know… not hideous. So on a whim I decided to give the Ajax Control Toolkit Autocomplete a try. I figured that if so many other people use it, why shouldn’t I? Or when properly translated: I hate dealing with style sheet issues and someone already had a control that works in both Firefox and IE.

Introduction… Skip if you know what this is already and just want the stupid code.

So where to begin? Well the autocomplete control itself is free and comes along with the Toolkit assembly.

Sounds good so far, so what does it do? It’s a “control”, for lack of a better word… more on that later, that can be used to attach to a textbox and allow a user to type in parts of a word and get back dropdown list like item… list.

Pretty good huh? What’s the catch? Well basically you need to use a web service to work with it, meaning either old school (.asmx?) or new school Communication Foundation services. For this example I will actually be doing it the “hard” way and use WCF. I’ve done it with both, but I figure I might as make it the more difficult of the two for fun. If I remember, the old web services are really easy to do this with. Another catch is that the web service has to be on the same server as the project.

So what isn’t it? End of world hunger, world peace, or the meaning of life. Sorry, I can only give you one of those and the autocomplete doesn’t cover that subject.

End Introduction and Begin the stupid code

Ok so you want to use the autocomplete control, huh? Well, you’ve come to the right place.

For this example, I’ll be doing the most simple version of adding the autocomplete control. This basically means setting up the service and creating some markup. Really easy. Next post I will get into how to create a web control class in a non web assembly.

Right off the bat you’ll need the toolkit assembly and create a project reference to it. Next you have to set up the WCF Service which is actually a lot easier than it sounds? Why? Because Microsoft was nice enough to create a default one for us. I’ve created a folder named Service (Brilliant!) and then I right clicked and chose Add New Item -> Ajax-Enabled WCF Service (I called it AutocompleteWebControl)… and boom already almost there.

You should now have a AutocompleteWebControl.svc.cs file in the folder and if you look at the code you get this:

namespace Test.Frontend.Service
{
    [ServiceContract(Namespace = "")]
    [AspNetCompatibilityRequirements(RequirementsMode =
      AspNetCompatibilityRequirementsMode.Allowed)]
    public class AutocompleteWebControl
    {
        // Add [WebGet] attribute to use HTTP GET
        [OperationContract]
        public void DoWork()
        {
            // Add your operation implementation here
            return;
        }
    }
}

Only thing of real importance at this point is the method with the [OperationContract] attribute. If you are going to expose a method to the autocomplete it has to have this tag. Now as you can see, we’ll need a method. At this point though I have to note two things that for the method to be correct:

  • It has to take in a String and an Integer. The first is the string that the user has typed in to search on, the second (If you choose to use it) is for limiting the number of items back. (This is set by the CompletionSetCount property on the control, more on this later.)
  • The second thing is that without any changes to how the control works, you have to send back a list of strings. This could be a deal breaker if you need to send back more information. I think it’s possible to do so, but I haven’t gotten to that point yet.

Ok so let’s create a quick method. My example is using the typical Linq to Sql stuff I’ve been using but I have faith you can figure out how to get some kind of needed information whether it’s LInq to Sql, NHibernate, LLBLGEN, or Stored Procedures…

....
  [OperationContract]
  public String[] GetUserNameList(String prefixText, Int32 count)
  {
    String[] userNames;

    userNames = LinqData.DataClasses.User
        .GetUserListByLikeName(prefixText)
        .Select(currentUser => currentUser.UserName)
        .ToArray();

    return userNames;
  }
....

Now I didn’t use the passed in integer, but I didn’t need it for this situation. As you can see this method, however follows the two rules: Takes in a string and integer and returns a string array.

Now you have the servce set up, next up is the mark up and let me tell you, it’s freakishly hard.

<%@ Register assembly="AjaxControlToolkit" namespace="AjaxControlToolkit"
tagPrefix="controlkit" %>

<asp:ScriptManager ID="smMain" runat="server" />
<asp:TextBox ID="textboxTarget" runat="server" />
<ajax:AutoCompleteExtender ID="autoCompleteMain" runat="server"
  ServicePath="~/Service/AutocompleteWebControl.svc" ServiceMethod="GetUserNameList"
  CompletionSetCount="10" MinimumPrefixLength="1" TargetControlID="textboxTarget" />

So there it is. Now you have a working autocomplete. But just in case you need it, I’ll run through this stuff.

ServicePath – This is where the web service is “located” relative to the project.

ServiceMethod – This is the name of the method it will call to fill itself.

CompletionSetCount – This is the other parameter passed into the web method and used if you want to limit the count of items returned.

MinimumPrefixLength – The minimum amount of characters needed to trigger the method call.

TargetControlID – Come on, honestly? You can’t figure that one out?

At this point you’re thinking this is great and all but what if you want to make a composite control? Well that’s the next post and it’s fairly easy.