5.25.2006

Atlas: Smart Auto Completion

Auto Completion without a Web Service



To get the latest version that works with Beta 2, please visit my new blog:
http://weblogs.asp.net/infinitiesloop/



If you haven't heard of the Atlas project yet, this article may not be for you. But even then, reading this may give you a clue as to the capabilities of Atlas. To quote the Atlas site,

"Atlas" is a free framework for building a new generation of richer, more interactive, highly personalized standards based Web applications.

One of the innovations Atlas brings to the table is its level of integration with the server side. It is because of this integration that makes it possible for you to take advantage of Atlas' advanced client side features without leaving the comforts of the server side of the world.

But despite this client/server integration, Atlas is still a truly client side framework, one that can be integrated with any server side back end, not just ASP.NET. Its design must take that into consideration, because everything it does must (and should) be a purely client side game. But if you are definitely using Atlas with ASP.NET, it would be nice if you could rely on deeper integration into the rich asp.net server side world. And that is what this article is all about.

Using the Auto Complete Extender


First, lets go over how the built-in stuff works. The built-in Atlas AutoCompleteExtender adds intelligent auto completion behavior to a textbox. Here's how you set one up:

First thing you need is a script manager:

<atlas:ScriptManager ID="ScriptManager1" runat="server" />
And then place a textbox and attach an AutoCompleteExtender to it:

<asp:TextBox id="txt1" runat="server"/>

<atlas:AutoCompleteExtender id="ext1" runat="server">
<atlas:AutoCompleteExtenderProperties Enabled="true"
ServicePath="SuggestionService.asmx"
ServiceMethod="GetSuggestions" TargetControlID="txt1" />
</atlas:AutoCompleteExtender>
The behavior uses the given ServicePath and ServiceMethod properties to call the specified Web Service whenever suggestions are needed. The web service, written by you, can query a database or do whatever it needs to do in order to calculate the suggestions. Here is an example of a web service that provides the necessary method signature:

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class SuggestionService : System.Web.Services.WebService
{
public SuggestionService()
{
}
[WebMethod]
public string[] GetSuggestions(string prefixText, int count)
{
return new string[] { "abc", "def", "ghi" };
}
}
The prefixText parameter is the text the user has entered thus far, and the count parameter is the maximum number of suggestions you should return. And just like that, we have auto-completion!


Auto Completion via a Web Service

Going one step further


It's the greatest thing since the variable geometry nacelle. But, there are some limitations to this approach. Because it must call a web service, the logic for determining the suggestions is isolated from the page that contains the textbox. That means you do not have access to any state information that is available on the page. In many cases that may not be an issue. It may even be good design to isolate that logic into a web service. But because you lack that state information, you are forced to configure the web service via global means such as the web.config. For example, a connection string. What if a developer wants auto completion for different database than the one the rest of the application is using? What if the suggestions that you want to show depend on the value of another control on the page, such as a date range that should limit the search results of the query? Or maybe you have a "product category" dropdown and the textbox should only suggest results for products that are in that category? What if you are a control developer (like me) and you want to create a custom textbox control that has auto completion built into it -- how will you effectively package together your custom control and the web service? Why should I have to create a web service to provide auto completion at all?

Why can't I wield the power of auto-completion all within the page itself?

Yes... Let's do that. Presenting the SmartAutoCompleteExtender and the SmartTextBox. In creating these two controls I had a strategy in mind:

  1. Create an Auto Complete extender that uses a CALLBACK rather than a web service. This will allow all the logic to calculate the suggestions to live on the same page.

  2. Support a Web Service too, for flexibility.

  3. Utilize the existing auto complete behavior script, so I don't have to write complex JavaScript.

  4. Raise an Event in the Extender control when suggestions are needed. The event model will allow users of the extender to provide suggestions easily within the page and multiple listeners could potentially work together to create suggestions from different sources.

  5. Create a TextBox with a built-in Auto Complete extender, so users of that control can provide auto completion without even knowing what Atlas is


This being my first custom extender for Atlas, I did run into a few problems. But in less than a day I was able to piece these controls together. If I had to do it again, already having learned all the lessons that I did, I could probably do it on the order of a few hours. This is a testament to the extensibility of Atlas. More on that later.

First, let us look at the SmartAutoCompleteExtender. To use it I must register my custom control assembly and namespace with the obligatory Register directive at the top:

<%@ Register Assembly="Infinity.Web" Namespace="Infinity.Web.UI.WebControls" TagPrefix="i88" %>
i88 is a nice tag prefix I like to use. Now lets replace the built in atlas extender with the smart one:

<i88:SmartAutoCompleteExtender Enabled="true" id="ext1" runat="server">
<i88:SmartAutoCompleteProperties
TargetControlID="txt1" />
</i88:SmartAutoCompleteExtender>
Notice there's no ServicePath or ServiceMethod specified. This extender uses an event on the server side instead. But if you wanted to use a web service, it supports that too:

<i88:SmartAutoCompleteExtender Enabled="true" id="ext1" runat="server">
<i88:SmartAutoCompleteProperties
TargetControlID="txt1"
Mode="WebService"
ServicePath="SuggestionService.asmx"
ServiceMethod="GetSuggestions" />
</i88:SmartAutoCompleteExtender>
But, we're more interested in the event. Just to keep these code lines shorter (screen real estate is prime on this blog .. I need a better medium!), create a namespace alias in your code behind:

using I88=Infinity.Web.UI.WebControls;
Then you can hook into the event on the extender like so:

protected override void OnInit(EventArgs e)
{
this.ext1.AutoCompleteCallback += new I88.EventHandler(ext1_AutoCompleteCallback);
base.OnInit(e);
}
AutoCompleteCallback is the event that fires when the client side needs suggestions. Now for the event handler itself:

void ext1_AutoCompleteCallback(object sender, I88.AutoCompleteEventArgs args)
{
int count = args.Count;
string prefix = args.Prefix;

args.CompletionItems = new string[] { prefix + "A", prefix + "B", prefix + "C" };
}
The event argument passed to the event handler contains three properties:

  1. Count - The maximum number of suggestions that should be returned

  2. Prefix - The characters entered so far into the textbox

  3. CompletionItems - a string array of suggestions to be set by you.
Just for demonstration and to prove it is working, we take the prefix and create three suggestions by adding "A", "B" and "C" to it. Here we go:


Look ma, no web service!

Excellent. The beauty of this is that it really was not very hard to do. I was able to reuse the existing javascript behavior that is defined for the built-in AutoCompleteExtender. The custom behavior javascript simply creates an instance of the built in behavior and lets it do all the dirty work. All that was required is to hook into the timer object it uses by replacing its event handler with my own, and replacing existing methods with your own is easy to do with javascript. To do the actual callback, it uses asp.net's built-in javascript function for that, too: WebForm_DoCallback. By passing it the ID of the extender control, and implementing ICallbackEventHandler in the extender control, its easy to raise the auto complete event.

Going one step further, again


Indeed why stop there... wouldn't it be nice if you didn't even need to create an extender? Why can't auto complete be a built-in feature of the textbox itself? Man you sure are demanding. Fine...

Get rid of the extender declaration. Then replace the TextBox with, well... the i88:SmartTextBox:

<i88:SmartTextBox ID="txt1" runat="server" EnableAutoComplete="true" />
Don't forget the EnableAutoComplete="true" attribute, because by default it is disabled. You might wonder why I didn't call this control "AutoCompleteTextBox" instead. Well because I don't believe in naming controls (or classes) after their features. The SmartTextBox might one day be extended to support many other advanced features, of which Auto Completion would be just one. Just planning ahead a little. "Smart" may not be the best name either, but its the best I could come up with ok? :)

Internally, the SmartTextBox creates a SmartAutoComplete extender for you. It also surfaces a property that allows you to have access to all the same properties the extender does. So once again you can use a web service or a callback, whatever floats your boat:

<i88:SmartTextBox ID="txt1" runat="server" EnableAutoComplete="true"
AutoComplete-Mode="WebService"
AutoComplete-ServicePath="SuggestionService.asmx"
AutoComplete-ServiceMethod="GetSuggestions" />
But as before, we're only interested in the callback mode for this article. The SmartTextBox also surfaces the event itself -- so if all you knew about was the SmartTextBox control, you could quickly and easily add custom auto completion to it, without ever hearing the word "Atlas" muttered. Change the event handler like so:

protected override void OnInit(EventArgs e)
{
this.txt1.AutoCompleteCallback += new I88.EventHandler(txt1_AutoCompleteCallback);
base.OnInit(e);
}

void txt1_AutoCompleteCallback(object sender, I88.AutoCompleteEventArgs args)
{
int count = args.Count;
string prefix = args.Prefix;

args.CompletionItems = new string[] { prefix + "A", prefix + "B", prefix + "C" };
}
And put it into action... remember to type at least 3 characters, because the default minimum length is 3. That is a property you can change if you like.


Look ma, no web service AND no Extender!

Yes I cheated -- this screenshot is exactly the same one as before. But that's because it looks exactly the same anyway. Even the 'view source' on the page looks exactly the same. The only difference is the declaration in the form.

Download the source code here!

I should also mention that the project type is the Web Application project option introduced by Microsoft, described in detail and available for download here. If you don't have it already, you should. It will be baked in on the first service pack for VS2005 anyway. If you'd rather not, then you'll have to rebuild the project file, or perhaps you can change the project type guid so it's a class library project instead. Sorry for the confusion.

Use the source however you like... change it, trash it, claim it as your own, I don't mind :) All I ask is you send some friends over to this tiny corner of the internet. I enjoy having readers. :)

Happy coding!

UPDATE 06/08/2006:

Someone pointed out a bug with the project on the asp.net forums. Click here to read the post. I have re-uploaded a new project with the fix.

I also added a new property to the extender: EnableCache (boolean). You see, the built in behavior has a nice little performance feature built into it. Once it requests suggestions for prefix "abc", it remembers them in a cache variable on the client. So if you type in "abcd", wait for the auto complete to occur again, then delete the "d", the behavior is able to recall the suggestions it already calculated without calling the webservice or performing another callback. But this presents a problem in callback mode if you try to use this custom extender in the ways it is advertised, where the suggestions may depend on the state of other controls on the page. The state of those controls may change, and the cache of suggestions will be wrong. And so it was simple to add the EnableCache property. Normally you should leave this option alone. Only disable the cache if you know you might give different suggestions for the same prefix text, because the values are dependant on other controls.

And finally, I have also included a sample web application that uses the SmartTextBox in callback mode. It also contains a RadioButtonList, and the suggestion items vary based on the selected value of the list.

Thanks to ethos42 for the bug report!
Download the Source Code here!

UPDATE 06/10/2006:

Unfortunately for me but fortunate for you guys, jjradke pointed out another bug. The event will fail to fire if you place the textbox within a naming container (for example within a template column of a datagrid, among other things). The bug was due to it using the ClientID instead of the UniqueID... which has been fixed!! If you already downloaded the source you can easily patch your copy by changing this line (approximately line 90 in the SmartAutoCompleteExtender.cs file)

writer.WriteAttributeString("id", this.ClientID);

To this:

writer.WriteAttributeString("id", this.UniqueID);

Thanks for the bug report!

UPDATE: 08/24/2006:

I'm sorry to have put you guys through downloading from FilePlanet. The link eventually broke, but thankfully I've found a more suitable home for the source code. The download links should work once again.

92 Comments:

Anonymous Anonymous said...

Could you post a working copy of a webform that utilizes this assembly. I was unable to get it to work. This is a great control, I have been really needing this functionality, thanks.

June 07, 2006 8:47 AM  
Anonymous Anonymous said...

Nice stuff Dave! Do we have this in our web controls. :-)

June 07, 2006 9:49 PM  
Blogger Infinity88 said...

A user has pointed out a bug with this control on the following post:

http://forums.asp.net/thread/1308201.aspx

I have a fix and will be republishing it shortly. I will also throw in a sample page as requested! Thanks :)

Bob -- we don't have Atlas integrated yet, but when we do, throw this in :)

June 07, 2006 10:40 PM  
Blogger Infinity88 said...

The fix is posted. Read the update paragraph at the bottom of the article for details.

June 08, 2006 8:50 PM  
Anonymous Anonymous said...

I am not sure what I am doing wrong. But i get the error:
Assertion Failed: Unrecognized Tag InfinitySmartExtenders:SmartAutoCompleteBehavior

Says it's not registered.

I built the control project. Added the ref. to the sample site and tried to run. Builds ok before the error.

I am prob. doing something wrong ...thx for any info.

June 22, 2006 9:24 AM  
Anonymous Anonymous said...

I really like your work and I would like to get this sample project working for me. The only problem is that I don't know how to build the control...
I know it's included in the second .ZIP file, but I have to complie it into a .DLL - correct?
Could someone direct me in the direction on how to do that?

Thanks in advance.

June 24, 2006 12:42 PM  
Anonymous Anonymous said...

For those of you struggling out there to get this project working… here is what you need to do to get it working:
- As mentioned in the article, download and install the "Visual Studio 2005 Web Application Project" here: http://webproject.scottgu.com/ . It's a plug-in for Visual Studio which will eventually become apart of Service Pack 1 for VS.
- Once you download the Infinity source code (ziped) you will find two more zips inside. You must first build the "SmartControlProject.Zip" from Visual Studio. But to do so, you will be missing two references, the "Microsoft.AtlasControlExtender" and the "Microsoft.Web.Atlas" DLLs. You can download Microsoft Atlas here: http://www.microsoft.com/downloads/details.aspx?FamilyId=B01DC501-B3C1-4EC0-93F0-7DAC68D2F787&displaylang=en . The second DLL can be found in the "Atlas" Control Toolkit. You can download it at the "Download" second at www.atlas.asp.net (as well as the Atlas framework mentioned before).
- Once you build the application, nothing will appear to happen, however the "Infinity.Web.dll" will have been generated and placed in the ".bin" directory. Save this somewhere else and then add it to a .bin directory for the first .Zip "SampleWebApplication".
- For the sample application, you need to also reference the same Microsoft DLLS (as do did for "SmartControlProject.Zip") and of course, the "Infinity.Web.dll" one you just built. If you get a compilation error regarding a missing "Skin1", just delete that out of the ASP code, you don't really need that to see the code working.
- And you should be all set. Enjoy!

June 26, 2006 7:40 AM  
Blogger Infinity88 said...

Thanks for the steps Coder :) I appreciate it!

Another way to get both projects running are to have them in the same solution. So you don't need to build the Infinity.Web.dll and copy it into the other project.. the one just has a project reference to the other. Of course you still need Atlas and the Atlas Control Toolkit.

June 26, 2006 8:48 AM  
Anonymous Anonymous said...

Sounds like a great improvement. I tried to download your source but got "Access denied. Invalid user name or password"

June 26, 2006 11:12 PM  
Blogger Infinity88 said...

You don't need an ID or password to download from filefront, perhaps they were just having some technical issues. It seems to be working as of right now. If you still can't download it send me an email and I'll send it to you. My email is in my profile. Thanks.

June 26, 2006 11:39 PM  
Anonymous Anonymous said...

This comment has been removed by a blog administrator.

June 29, 2006 9:22 AM  
Anonymous Anonymous said...

I have a question for the author.

Is there a way to format the contents of the 'DropDownPanel' equivalent of the Atlas AutoCompleteExtender for the Infinity SmartTextBox ? (For example change the color/font of the text the appears in the drop down box below the SmartTextBox)

The way you do it with the standard Atlas AutoCompleteExtender is to set-up a Div tag and then set it to DropDownPanelID property of the AutoCompleteExtender. But that property doesn’t exist in the Infinity component.
I love this new component Infinity has developed, but unforchanetly this is the only feature that keeps me from being able to use it.
Thanks for any help!

July 01, 2006 4:19 PM  
Blogger Infinity88 said...

Yes I definitely overlooked that feature. I will have to add support for it. I will update it very shortly! Thanks :)

July 02, 2006 9:31 PM  
Anonymous Anonymous said...

How would I add behaviour to return associated key values for all completion items. I really like the control but need to be able to save the identity of a selected item that the user selects. Would I use hidden fields?
Any suggestions?

Thanks

July 03, 2006 3:31 PM  
Anonymous Anonymous said...

How would I extend this control to return text/value pairs for the completion items? I really like the control but I need to be able to save a value for the selected text instead of the text itself. Would I use hidden fields?

July 03, 2006 3:34 PM  
Blogger Infinity88 said...

The fact you are presenting a textbox to the user indicates a free form (although possibly validated) field. If you presented text/value pairs and the user selected "abc" with value 123, how would you get 123 if the user simply _typed_ "abc" without selecting an item?

It sounds like you might be better off using a different UI story. If you have a relatively small number of items the user can select from, consider using a ListBox instead. TextBox auto completion is better suited for things where the text is all you need -- which is presumably the case since again, you're presenting a free form textbox to the user. If they aren't allowed to type whatever they want, a TextBox may not be appropriate.

If you're still set on using an auto complete textbox I'm afraid you'll have to look elsewhere at other 3rd party controls to accomplish what you want.

July 03, 2006 3:57 PM  
Anonymous Anonymous said...

Great work i88, yours is among my favorite implementations.

I have created one too, wrapping the js control by ScriptAculoUs, which has some nice features too like an UpdateProgress-like control which notifies the lookup progress. You can find it here, together with a list of the others implementations i like.

July 04, 2006 6:48 PM  
Anonymous Anonymous said...

I got the control to work and it seems to be working great except for one problem: the list of suggestions is sometimes partially hidden by other controls on the page. Is there an easy way to fix this, possibly by increasing the z-index? Please help.

July 12, 2006 11:23 AM  
Anonymous Anonymous said...

Quick question: on every postback (every keystroke), is all of the code-behind supposed to run or just the code related to the control? from my understanding of how atlas works, i thought just the information related to the control was posted back and that just the server code related to that control was run. is this not true? for some reason, in my implemention of this control, it is running all the code...

please let me know.

thanks

July 13, 2006 6:55 AM  
Blogger Infinity88 said...

>> the list of suggestions is sometimes partially hidden by other controls on the page <<

Thats an unfortunate browser issue... certain elements like dropdowns are ALWAYS on top of everything, despite the z-index. The hack around it is to place the element you want on top of an empty IFRAME, because it so happens that an IFRAME is the one and only thing that will actually show up 'on top' of those elements. If the javascript behavior isn't doing that already, there isn't much you can do about it short of rewriting the javascript behavior so that it does. Perhaps this should be a feature request to the Atlas team.

July 18, 2006 10:41 PM  
Blogger Infinity88 said...

>> i thought just the information related to the control was posted back and that just the server code related to that control was run <<

Callbacks are full-blown postbacks, so everything runs. OnInit, OnLoad, etc. It does stop short and avoid PreRender and Render for obvious reasons, but the page life cycle is more or less left intact. One obvious reason for this, as it seems to me, is that there is the possibility that some piece of the life cycle for the page is critical to the operation of the control performing the callback. It could be security related, for example.

July 18, 2006 10:44 PM  
Anonymous Anonymous said...

I have your SmartAutoComplete in my application. It seems to be working fine, except I have a gridview on the page that is using paging. When I select a different page, from the gridview, the page returns without the gridview showing.

I remove your control and the gridview works correctly with paging.

I do notice that with your control on the page, and I click a new page on the Gridview, your SmartAutoCompleteProperties.cs is executed. It doesn't seem like it should.

Any ideas?

Thanks

July 26, 2006 8:36 AM  
Anonymous Anonymous said...

Hello. Has anyone used the Smart Auto Completion control with a secure site, using SSL? Everything works, it's just that a pop-up message comes up (using IE6) saying that "This page contains both secure and nonsecure items. Do you want to display the nonsecure items?"

I know there is a way to disable the message by changing the default settings for IE6 on the client side but I was hoping there was another way around this. I don't want all my users to have to go through that if they don't have to.

Please let me know. Thanks in advance.

July 26, 2006 8:42 AM  
Blogger Infinity88 said...

djosic... do a little experiment for me. Put a dropdown control next to your textbox. Then see if the autocomplete popup (the thing that contains the suggestions) appears on top of or beneath the dropdown.

If it appears on top of it, then the behavior is using an Inline Frame trick to get around a browser bug where nothing can appear on top of certain elements (like dropdowns). The Inline Frame is the only element that can appear on top of one, so the behavior is using an IFrame with the suggestion items layered on top of it in order to give the illusion that its all working as you'd expect.

The trouble is the inline frame is pointed at about:blank or some other "blank" equivilent, and that is producing the "non secure content" warning. Unfortunately there isn't much you can do about that without rewriting the behavior. Atlas is a moving target, still under development, so things like this are likely to creep up. You may just have to wait until the next CTP drop. I'd attempt to solve this problem but I dont think I'm going to have time to anytime soon :(

If it does NOT appear on top of the dropdown, then it is not using an inline frame. And in that case I'm not sure what would be causing the error.

July 26, 2006 9:25 AM  
Anonymous Anonymous said...

The suggestions are coming up on top of the drop down control like it's supposed to. So I guess there is no solution for now...

I am going to try a blank page with nothing but the drop down control and the auto-complete control and see if it gives me the same message for the secure site.

July 26, 2006 10:01 AM  
Blogger Infinity88 said...

Doug -- that does sound bad. It could be a bug with how the callback is performed. It may be interfering with the callback the gridview makes, I'm not sure. I will have to try and duplicate it later tonight and see what I can do about it. Thanks for the report, let me know if you get any more info on it.

July 26, 2006 10:16 AM  
Blogger Infinity88 said...

Doug, fortunately or unfortunately I can't duplicate your issue. I've got a simple page with only a gridview and a smartextbox on it, and its working alright.

Here's a screenshot of it working:

http://infinity88.com/images/blog/gridviewandautocomplete.gif

July 26, 2006 8:01 PM  
Anonymous Anonymous said...

Infinity88,

I am sorry I didn't get back to you sooner on the paging issues using the Gridview.

I did find a problem in my code and I am sorry I waisted your time.

Your control is working properly and I thank you for your support.

Doug

July 31, 2006 10:48 AM  
Anonymous Anonymous said...

Has any one figured out how to do this in vb

August 01, 2006 12:37 PM  
Blogger Pastor Shawn said...

I'm running VS2005 version 8.0.50727.42. I tried to open "SmartControls.csproj" and it gave me the "project type not supported" error. So, I installed the VS update at webproject.scottgu.com, rebooted my computer, and tried to open the project... and got the same error. Do you know what could be causing this?

August 05, 2006 2:23 PM  
Blogger Pastor Shawn said...

Regarding my previous comment... nevermind! There were two files I needed to install on the MSDN page. I only installed the first. I got the project to open now.

August 05, 2006 2:30 PM  
Blogger Infinity88 said...

Hmmm it should work. I probably shouldn't have made it a web project. I'd recommend just recreating the project from scratch. Just start a new blank project and add the source files to it.

August 05, 2006 2:31 PM  
Blogger Infinity88 said...

Nice :) You beat my comment. Glad you got it working :)

August 05, 2006 2:32 PM  
Blogger Pastor Shawn said...

I was able to put your control in my project and have it working in a few hours. This control is HOT! I was so disappointed when I learned that the Atlas autocomplete control wouldn't allow me to filter the list based on form data. Now, you're my hero! THANK YOU for taking the time to write this and sharing it with us :).

August 05, 2006 4:48 PM  
Anonymous Anonymous said...

This control is great. I used a modified version of it for something I'm working on. But here's a question for you...

What if you want to apply styles to the text in the autocomplete box? I haven't been able to find a way.

August 07, 2006 11:36 AM  
Blogger Infinity88 said...

Anonymous --

The built in extender allows you to specify a DIV of your choice to use as the dropdown that contains the suggestions. Unfortunately I didn't carry that feature forward into the Smart version.

It should be fairly simple to add the feature back in (just passing it through to the contained behavior) I just haven't had any time lately :( If you managed to add it back in I would happily update it here :)

August 07, 2006 11:40 AM  
Anonymous Anonymous said...

I attempted to do just that, implement the same feature so I could specify my DIV tag. Unfortunately I couldn't get that working.

I assumed that you would just use mAutoCompleteBehavior.set_completionList ( value ), and provide a reference to the actual DIV element that could be obtained with getElementById.

That didn't work though. Maybe I did something wrong?

August 08, 2006 11:31 AM  
Anonymous Anonymous said...

I actually got the feature in there... Stupid on my part. I used document.getElementById to find my DIV element and use AutoCompleteBehavior.set_completionList to assign it.

But let me tell you something... figuring out the default styles that are used with the normal AutoCompleteExtender is not an easy task. I opened the axd file that has all of the initializations in there and set the styles on my DIV element so it matched... but there must be more styles that are set some place else.

Any ideas on what a css class should look like with this?

August 08, 2006 1:01 PM  
Blogger Infinity88 said...

It looks like it applies the styles you are referring to whether or not it is the built-in div so it shouldn't really matter.

Part of the confusion is because the behavior uses a popup behavior internally, which I guess might manipulate the div style even further (such as positioning and sizing it to fit along side the attached textbox).

Is your custom div showing up badly?

August 08, 2006 1:49 PM  
Anonymous Anonymous said...

Yes, the DIV shows up very poorly. It's almost like there's two of them or something. There's a small autocomplete box in the forground with nothing in it, then the content shows up behind everything with no border... really strange.

I've read some place that the custom DIV should be a server side control. Is this the case? Should I use a pannel instead of a DIV element?

August 08, 2006 2:05 PM  
Anonymous Anonymous said...

Very nice! You have just saved me hours of time, exactly what I was looking for!!!

August 14, 2006 8:04 AM  
Blogger Luxspes said...

Great, completely and absolutely greate, loved you article, loved your code, it was exactly what i was looking for!

August 14, 2006 9:10 AM  
Anonymous Anonymous said...

I've got a couple quesitons.

I'm using this in a gridview, when a row is in edit mode. If I send a row into edit mode, and then back to read only. Then send that same row back into edit mode, I get an error about using a duplicate id for the SmartAutoCompleteExtenderBehavior.

It seems that the Behavior object should be removed from the collection when the text box is removed. Is there a way to accomplish this?

August 16, 2006 8:54 AM  
Anonymous Anonymous said...

Hi Infinity, Any update on the DropDownPanel format mechanism?

August 16, 2006 10:24 AM  
Anonymous Anonymous said...

This is a fantastic control.

When this control is inside of an update panel with other controls it seems to generate an error when the other controls launch an event:

'Assertion Failed: Duplicate use of id "ct100$ContentPlaceHolder1$ctl37" for object of type "InfinitySmartExtenders.SmartAutoCompleteExtenderBehaviour".'

The offending controls are textboxes and dropdownlist which have updatepanel triggers set via a ControlEventTrigger. Anytime these trigger an event the error comes up.

Any ideas?

Thanks!

August 16, 2006 11:57 AM  
Anonymous Anonymous said...

Just to avoid confusion i should have said in my previous post:

This is fantastic control, I do have one question however.....

Otherwise my original statement would sounds sarcastic.

Thanks again!

August 16, 2006 12:04 PM  
Blogger Infinity88 said...

Steve --

I've duplicated the issue. I can't say exactly what is causing it, but its due to the fact that the SmartTextBox contains an Extender control. I think you would get this error if you put any extender on the inside of an update panel. Update panel doesn't seem to handle containing an extender.

The solution is easy though -- you need to divorce the textbox from the extender. The relationship just isn't working out.

So instead, put a regular textbox inside the update panel, and then outside of it, probably at the bottom of the page, put a i88:SmartAutoCompleteExtender (and corresponding i88:SmartAutoCompleteProperties) and link it to the regular textbox.

Let me know how it goes. Thanks for the comment!

August 16, 2006 5:40 PM  
Blogger Infinity88 said...

Yonkz -- same issue for you! Sounds like you're using an update panel. Follow the advice I gave Steve (above).

August 16, 2006 5:42 PM  
Blogger Infinity88 said...

Anon --

About the custom ListElement. I can't even get to first base with it at the moment. I can't get a custom div to appear as the list element. Would you mind sending me what you have, perhaps it will jog my brain :)

August 16, 2006 6:15 PM  
Anonymous Anonymous said...

infinity88,
Thanks for the suggestion, but it doesn't seem to work.

Here's the scenario:
I've changed the textbox back to a regular textbox (the textbox is only present when a grieview row is being edited), and added a SmartAutoCompleteExtender outside of the update panel (also tried inside the update panel with the same results.)

In the page init event I disable the extender, and clear it's targetproperties to prevent it from throwing errors.

On the row databound event of my gridview, I create a new SmartAutoCompleteExtenderProperties object, and set the targetControlId to the UniqueID of the textbox in the gridviewrow that has a rowstate of edit, and it's mode to callback. I then add the properties object to the extender object, and enable the extender.

It is at this point that my gridview does not go into edit mode. That's not to say that the rowstate is never == edit, but the textboxes are never shown in the browser. I've tested my update panel, it is working properly.

If I do everything but enable the extender, My gridview behaves as expected.

I can get the original autocomplete extender to work using this method.

Any ideas:

August 17, 2006 5:50 AM  
Anonymous Anonymous said...

Got the update panel thing figured out for all interested parties.

Add these couple of lines of code in the dispose method in the .js file:
var applicationMarkupContext = Sys.Application.getMarkupContext();
if (applicationMarkupContext)
{
applicationMarkupContext.removeObject(this);
}

Life is good once you do this!!!!!

August 17, 2006 11:20 AM  
Anonymous Anonymous said...

I was wondering whether it is possible with the Autocomplete extender to save the id of the record with the name that is send over and when the name is selected from the autocomplete extender to get the id again.

August 18, 2006 2:43 AM  
Anonymous Anonymous said...

Thanks Yonkz and infinity:

I got the problem solved. Now I am wondering how to raise an event when an item in the list is selected. I need to run some code when one of the items is chosen and textchanged is no good.

Thanks again.

Steve

August 22, 2006 9:02 AM  
Anonymous Anonymous said...

Actually I am still having problems with the update panel. I tried both Yonkz and infinity's suggestions to no avail.

Maybe it is incompatible with UpdatePanel?

August 22, 2006 2:01 PM  
Anonymous Anonymous said...

I get the following error when trying to download the source.

"Invalid Key or in use or Missing File

Your download key for the requested file is invalid. Download keys are only valid for 48 hours. Once your download is complete, the key is no longer valid. Keys are also only valid for the original server.

Additionally this error may be caused because the file was not found on the server.

If you need help starting your download, please contact FileFront support."

August 24, 2006 7:12 AM  
Anonymous Anonymous said...

thank you for your hard work.
i have a request. I want to use the auto complete feature in a text box to show me all the values in the database but I dont want to select one. I want to check as i type if there is a similar value in the databse if not then i can go ahead and enter the value.
your help would be greatly appreciated.

sebastian

September 12, 2006 2:39 PM  
Blogger Infinity88 said...

sebastian -- nothing prevents you from typing whatever you please into the textbox. The auto complete items are just "suggestions" that you don't have to follow.

September 12, 2006 2:49 PM  
Anonymous Anonymous said...

Great blog i88. I am hoping you can shed some light on my issue, which is:

The users of my website can enter multiple items in a textbox separated by a comma. I want to do autocomplete on the item they are currently entering. So, if I am typing "first, second, th", then the autocomplete should be using 'th' as the prefix test. I was able to get this part coded up correctly.

The part I am struggling with is the textbox content once the user makes a selection. In the above example, let's say that the autocomplete suggests "three" and the user selcts that item. AutoCompleteExtender will delete the existing text and replace with "three". I want it to show "first, second, three".

Can this be done easily?

September 14, 2006 3:44 PM  
Blogger Infinity88 said...

Anonymous -- sure you can. You just need in include the prefix data in the completion items.

So if the user enters "one, tw" then one of the suggestions should be "one, two", rather than just "two". You should be able to add back that stuff in the front once you calculate the suggestions.

September 14, 2006 8:51 PM  
Anonymous Anonymous said...

I know how to get it working if I showed the PrefixText in the autocomplete.

However, the issue here is that, I DO NOT want to show the the "one, two" in the suggestions list. I want to just show two.

September 14, 2006 11:32 PM  
Anonymous Anonymous said...

Hey this is really cool. I just came upon this blog the other day and I think your code can really help me. Thanks. But I have a problem which might not be your code, maybe it is with the way I set up the sample in VS. Anyway, it works great for postbacks but when I tested with the webservice I get the following error:
The server method 'GetSuggestions' failed with the following error:

Server Error in '/' Application.
--------------------------------------------------------------------------------

The type 'SuggestionService' is ambiguous: it could come from assembly 'C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\root\c368196d\30a3166a\App_Code.ozuescpg.DLL' or from assembly 'C:\Documents and Settings\(insert my username)\My Documents\Visual Studio 2005\Projects\WebApplication1\bin\WebApplication1.DLL'. Please specify the assembly explicitly in the type name.

Do you have any ideas what may cause that?

Thanks, Andy

September 22, 2006 8:14 AM  
Blogger Infinity88 said...

Andy, it sounds like you've just got some errant DLLs laying around. That or you have the code in both App_Code and you've compiled the app into a single dll. Clean out all build output completely and try again. You've just somehow got the same class compiled into two different dlls that are both loaded.

September 22, 2006 4:52 PM  
Blogger Luxspes said...

Hi, I really liked you code... but I am having a problem... what if the autocompletion string have a "'" comma? in that case... a single line for autocompletion gets splitted :(... I am not sure how to fix that...
Please, if you have a bit of time give some hints...

September 23, 2006 7:44 PM  
Blogger Infinity88 said...

luxspes --

Try encoding the comma. The code could handle that for you, but it doesnt :)

The html encoding for a comma is %2C

September 23, 2006 8:05 PM  
Blogger Luxspes said...

Thanks a lot :) I'll try the encoding...

September 24, 2006 11:34 PM  
Anonymous Anonymous said...

for the guy requesting a sample in vb:

assuming a smarttextbox with id txtMessageID -

Protected Sub txtMessageID_AutoCompleteCallback(ByVal sender As Object, ByVal args As Infinity.Web.UI.WebControls.AutoCompleteEventArgs) Handles txtMessageID.AutoCompleteCallback
Dim count As Integer = args.Count
Dim prefix As String = args.Prefix
Dim selectedValue As String = Me.MessageTypeList.SelectedValue

args.CompletionItems = New String() {prefix & selectedValue & "1", prefix & selectedValue & "2", prefix & selectedValue & "3"}

End Sub

September 26, 2006 1:28 PM  
Anonymous Anonymous said...

Did anyone figure out how to encode a comma? I tried using %2C, but I just get "%2C" in my selection.

Any comments would be helpful.

September 28, 2006 6:28 AM  
Anonymous Anonymous said...

First I must say nice control! It's jsut one thing I'm wondering about...How to set the MinimumPrefixLength? I haven't found a way to change it from the default 3.

September 29, 2006 2:47 AM  
Blogger Infinity88 said...

You should be able to set the MinimumPrefixLength on the autocomplete properties object.

Is that not working for you?

September 29, 2006 10:36 AM  
Anonymous Anonymous said...

Yes! You're right! I don't know how i missed that...Well it was friday afternoon...But I have another problem too..when i load the page i get the following popup error:
Assertion Failed: Unrecognized attribute "PageRequestManagerID" on object of type "InfinitySmartExtenders.SmartAutoCompleteExtenderBehavior" but i can still use the component after i have chosen either ok or cancel on the popup...any ideas what might be wrong

October 01, 2006 11:53 PM  
Anonymous Anonymous said...

I have an annoying problem. Every time I try to run a page with these objects I get a prompt with the following:

'Assertion Failed: Unrecognized attribute "PageRequestManagerID" on object of type "InfinitySmartExtenders.SmartAutoCompleteExtenderBehavior"

Break into debugger?'

I have rebuilt everything in Release mode and still can't prevent this prompt.

Any ideas on how to discover the genesis of the problem?

October 03, 2006 7:49 AM  
Anonymous Anonymous said...

I am also seeing the same 'Assertion Failed: Unrecognized attribute "PageRequestManagerID" behavior ...any ideas on this?

October 06, 2006 10:00 AM  
Anonymous Anonymous said...

Solution to PageRequestManagerID issue: add this to your property file for the extender...

// Hide inherited PageRequestManagerID from serialization to prevent
// it from being written to the XML Script. (Because the extender's
// behavior doesn't derive from BehaviorBase, it doesn't expect to
// be given a PageRequestManagerID property.)
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1706:ShortAcronymsShouldBeUppercase", Justification = "Following Atlas pattern")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "Doesn't work if static")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "value", Justification = "Setter is not implemented")]
public new string PageRequestManagerID
{
get
{
return null;
}
set
{
throw new NotImplementedException();
}
}

October 06, 2006 11:11 AM  
Anonymous Anonymous said...

Thanks Healer, you healed me!

October 09, 2006 11:04 AM  
Anonymous Anonymous said...

I have visual web developer express and can not open the project even after the update mentioned. Can you post a compiled .dll we can import as a tooltab?

October 17, 2006 8:25 PM  
Blogger Infinity88 said...

With the first Beta release of the Microsoft AJAX extentions, this control is due for an update.

I will be creating an updated version that works with the latest beta release asap. In the meantime please watch my new blog for updates:

http://weblogs.asp.net/infinitiesloop/

October 20, 2006 9:45 AM  
Blogger Luxspes said...

With the release of Microsoft ASP.NET AJAX v1.0 Beta... it seems that changes in API of AutoCompleteExtender ... make it necessary to drastically change the code... (for example TargetControlPropertiesBase just dissapeared)
Any hints in how to fix it?
thanks
bye

October 20, 2006 5:19 PM  
Blogger Luxspes said...

A friend and I have made it compile following the recomendations in http://ajax.asp.net/ajaxtoolkit/Walkthrough/AtlasToAspNetAjax.aspx
But now the problems is the javascript
I get a error saying Sys.TypeDescriptor is not defined :S

October 20, 2006 6:17 PM  
Blogger Luxspes said...

I have fixed the "," issue,
to know how take a look at
http://luxspes.blogspot.com/2006/10/fixed-problem-with-smartautocomplete.html
hope this helps
(and that if someone finds the way to upgrade this control into Beta 1 he/she will post a how-to tg ;) )

October 20, 2006 6:34 PM  
Blogger Luxspes said...

Okey, now my problem is AutoCompleteBehavior.... it just doesn't find it... I believe now it is inside Sys.Preview... but if I inspect Sys.Preview it says me is undefined... any hints?

October 20, 2006 7:12 PM  
Blogger Infinity88 said...

AutoComplete is:

Sys.Preview.UI.AutoCompleteBehavior

In the Microsoft.Web.Preview.dll.

I plan to create a new version targetting the new beta, I will publish it when it is available. I'm afraid I won't have time this week though. But I will certainly take into account the 'comma' problem :) Thanks for all your comments :)

October 20, 2006 7:30 PM  
Anonymous Anonymous said...

It would be very nice if you find some time to fix your SmartAutoComplete. I'm trying to fix it myself but there are some problem with AutoCompleteBehavior that I can't fix.

In your .js file you have var _autoCompleteBehavior = new Sys.UI.AutoCompleteBehavior(); and in new beta release there isn't Sys.UI.AutoCompleteBehaviour constructor. I tryed to change it in this._autoCompleteBehavior = $create(AjaxControlToolkit.AutoCompleteBehavior, {}, null, null, this.get_element()); but it doesn't work.

Please find some time :)

October 23, 2006 3:23 PM  
Blogger Luxspes said...

I found a bug in my solution to the "," problem, the problem is that basically
HttpUtility.UrlEncode is NOT equivalent to javascript "escape"
, so i have updated my post with the right solution.

October 31, 2006 8:32 AM  
Anonymous Anonymous said...

Thanks for this great control. It is wonderful. But I need to use the DropDownPanelID property of Atlas AutoComplete which I can not find.I have downloaded the source from your site and I assume this is the latest version. Could you please let me know if there is a version available with this feature. Thank you.

November 06, 2006 12:04 AM  
Anonymous Anonymous said...

Infinity88,

Thanks for working on getting this control compliant with AJAX Beta 1.0. Any estimates when you'll be done? I'm excited to use it...

November 08, 2006 1:56 PM  
Anonymous Anonymous said...

Hiya i88,

Great textbox! We are also waiting for the Ajax BETA 1.0 version, so let us know ;-)

Thanks for the great work!

November 10, 2006 6:44 AM  
Anonymous Anonymous said...

Everyone's hinting at the same thing. When will the AJAX Beta 1.0 version be done? Are you working on it? Please update on the status. I was considering building one myself if it was going to be too long. Thanks.

November 10, 2006 6:47 PM  
Blogger Infinity88 said...

Very very soon :) I've got it mostly done, just need to put on some finishing touches and package it up.

November 10, 2006 10:26 PM  
Anonymous Anonymous said...

Thank you. I wait impatiently. And forgot to mention in my previous post, great work!

November 12, 2006 3:56 PM  
Anonymous Anonymous said...

Any news? :-)

Here is the best place to look for it when you do release it right?

November 15, 2006 9:25 AM  
Blogger Infinity88 said...

Ok guys its ready its ready! So sorry for the long delay :)

Check it out at my new blog location:

http://weblogs.asp.net/infinitiesloop/

November 15, 2006 3:05 PM  
Anonymous Anonymous said...

Infinity88, thanks!

November 15, 2006 5:02 PM  

Post a Comment

<< Home