-
SweetTitles - fading tooltips (and my extender)
-
Dustin Diaz, among other cool things, has written a nice Javascript library called SweetTitles to convert hyperlink's Title attribute (Tooltip property in ASP.NET HyperLink web controls) - those yellow popups appearing when you hover the mouse over them - into nice fading boxes.
The picture below shows the effect change when using it:
You should know I'm becoming the wrapper man so I thought I would ease its integration with ASP.NET into a draggable web control - as well as enhance it a bit. The control I created is a simple extender control and all you have to do is drag it onto your webform to see everything happen magically. All the HyperLinks and <a> tags on your page receive that nice effect for free.
<asp:hyperlink id="HyperLink1" runat="server" navigateurl="~/SomePage.aspx"
tooltip="I link to SomePage.aspx">SomePage</asp:hyperlink>
<a title="I link somewhere else" href="/SomeWhereElse">SomeWhereElse</a>
The control is called SweetTitlesExtender, has no runtime appearance and exposes a single enum property called EmbeddedStyleSheet with 5 values:
- None - no stylesheet will be embedded, you'll have to write your own
- Classic - the one shipped by Dustin Diaz with the library
- Dustin - the one Dustin Diaz uses on his own website
- Blueish
- Greenish
- Reddish
That property allows to choose among some some stylesheets I have embedded into the assembly to provide some ready to use style options, which look like in the following picture (I'll let you guess which one corresponds to each enum value):
In case you want to provide your own style, set the property to None and create a stylesheet with the following structure:
body div#toolTip { position:absolute;z-index:1000; [...] }
body div#toolTip p { [...] }
body div#toolTip p em { [...] }
body div#toolTip p em span { [...] }
Since the original library is licensed under a Creative Commons Attribution Share Alike (by-sa) license, my control is under the same license.
Binary and source available.
-
Registering scripts into the page header with ASP.NET 2.0
-
UPDATE 19/08/2006: changed the API, no more public constructor but static property to access the instance of the HeadScriptManager.
UPDATE 03/08/2006: now the library allows to register stylesheets too. See class diagram below for details.
ASP.NET 2.0 pages expose a new property called ClientScript of type ClientScriptManager, which allows to manage client-side scripts, usually Javascript but not just that. Its public methods allow to render scripts in different parts of the page, as well as to register some client-side events.
In particular, scripts can be rendered just below the opening of the form tag or just before its closing, but it's not directly possible to include scripts into the head tag.
With ASP.NET 2.0 you may have noticed that web forms created with Visual Studio 2005 and family products automatically place the runat="server" attribute in the head tag of each page. That's why the Page class exposes a new property called Header, of type HtmlHead, which allows to interact with the page header and do something like including an external script:
HtmlGenericControl Include = new HtmlGenericControl("script");
Include.Attributes.Add("type", "text/javascript");
Include.Attributes.Add("src", "http://dev.virtualearth.net/mapcontrol/v3/mapcontrol.js");
this.Page.Header.Controls.Add(Include);
or like injecting code manually:
HtmlGenericControl Include2 = new HtmlGenericControl("script");
Include2.Attributes.Add("type", "text/javascript");
Include2.InnerHtml = "alert('JavaScript in Page Header');";
this.Page.Header.Controls.Add(Include2);
Looking at this post by Christopher Pietschmann (where I shamelessly got the above code) I had the idea of creating a library to extend the features of the ClientScriptManager class to the header of the page. Unluckily that class is sealed, it would have been nice to create a partial class to extend it... I always wonder why the guys at Microsoft don't let us exploit the power of the framework exposing some more of their internal, private, and sealed stuff. However what I came up with - thanks to Reflector to keep the API close to that exposed by the framework as well as to save time - is a simple class which can be used in the same way, and lets you render script blocks, script includes and embedded resources in the page header. To be more user-friendly it keeps the member names of its "parent" class. Here is the diagram:
UPDATE 03/08/2006: the class exposes a new set of methods with a similar signature which allow to inject stylesheets. The usage is the same, but they render the content inside <style> tags in case of embedded styles (RegisterHeadStyleBlock) or inside <link> tags in case of linked styles (RegisterHeadStyleInclude and RegisterHeadStyleResource). It comes useful mostly to control developers, so that you can inject embedded assembly resources.
UPDATE 19/08/2006: the API has changed and the constructor is not directly accessible. The instance of the HeadScriptManager can be accessed using the Current static property. The example below has been updated to reflect this change.
Now it can be used referencing the assembly in the project, creating an instance and calling its methods:
HeadScriptManager manager = HeadScriptManager.Current;
manager.RegisterHeadScriptBlock(this.GetType(), "scriptKey", "alert('hello');", true);
Source and binaries are available along with my main project, BusyBoxDotNet.

-
Atlas ThumbnailHyperlink: Hyperlink with page preview
-
I've been playing around with Atlas lately and decided to try to integrate an Atlas control extender into a ready-to-use web control. What I like most are the callback capabilities, but since many implementations already exist (kudos to this one) I switched to something else.
I picked up the ASP.NET HyperLink control and thought it would be nice if it displayed a popup whenever the mouse went over it, showing a preview of the page it pointed to (I got the idea from here). So I got it to meet the HoverMenu extender found in the Atlas Toolkit and built a control called ThumbnailHyperlink. It features the properties of an HyperLink plus the ones of the HoverMenu extender, so that you can choose where to show the preview, its offset and so on.
You can download a demo website and the source.
UPDATE: I'm really sorry but the website was on a free hosting company which decided to shut it down without informing me first. The code has gone since I didn't have a local copy. Really sorry about that.
-
Strongly Typed Table Adapters: autogenerating CRUD statements
-
Visual Studio 2005 features a tool called DataSet designer which lets creating DALs for ASP.NET applications fastly and using strongly typed objects. If you're new to this topic my advice is to check out the nice tutorials written by Scott Guthrie and Scott Mitchell.
When configuring the default query for a TableAdapter, at some time during the wizard you can choose to configure some advanced settings, as shown in the figure below:

Checking "Generate Insert, Update and Delete statements" instructs the wizard to infer the queries for manipulating the table data from the SELECT statement written in the previous wizard step. Visual Studio, in fact, can derive these statements from the SELECT clause in most cases, except when the SELECT clause contains JOINS between tables.
To make an example let me quote the tutorial written by Scott Mitchell which involves the Northwind database, which in turn contains a Products table:
"Note that the ProductsTableAdapters class returns the CategoryID and SupplierID values from the Products table, but doesn't include the CategoryName column from the Categories table or the CompanyName column from the Suppliers table, although these are likely the columns we want to display when showing product information. We can augment the TableAdapter's initial method, GetProducts(), to include both the CategoryName and CompanyName column values, which will update the strongly-typed DataTable to include these new columns as well.
This can present a problem, however, as the TableAdapter's methods for inserting, updating, and deleting data are based off of this initial method."
That is, if you write standard JOINS in the select query then Visual Studio can't create the other statements automatically - like shown below.
SELECT ProductName, CategoryName, SupplierName
FROM Products JOIN Categories ON Categories.CategoryID = Products.CategoryID
JOIN Suppliers ON Suppliers.SupplierID = Products.SupplierID
Luckily a workaround for this issue exists, and consists in specifying the JOIN clauses inside the SELECT list. Back to Scott's words:
"Fortunately, the auto-generated methods for inserting, updating, and deleting are not affected by subqueries in the SELECT clause. By taking care to add our queries to Categories and Suppliers as subqueries, rather than JOINs, we'll avoid having to rework those methods for modifying data. Right-click on the GetProducts() method in the ProductsTableAdapter and choose Configure. Then, adjust the SELECT clause so that it looks like:"
SELECT ProductName,
(SELECT CategoryName FROM Categories
WHERE Categories.CategoryID = Products.CategoryID) as CategoryName,
(SELECT CompanyName FROM Suppliers
WHERE Suppliers.SupplierID = Products.SupplierID) as SupplierName
FROM Products
Using this trick you'll end up having Visual Studio generate those statements for you even if you are joining tables.
-
A ScriptAculoUs autocomplete web control
-
To the reader - this post has evolved much and contains many comments. You don't need to read through them all to find things which have been forgotten or to find bug fixes and new features, because each of them, if valuable, has already been included in the release version of the code.
To contributors and readers - please don't use this post' comments anymore for anything related to the project, since it has now a dedicated page on the SVN hosting offered by Sourceforge, where you can submit issues, patches, ask questions and so on. All info can be found into this other blog post I dedicated to the topic.
UPDATE 24/08/06: Added some features and fixed some bugs, thank to Laurentiu Macovei, details in the post.
UPDATE 19/08/06: Removed property AdditionalControl and added property Parameters, details in the post.
UPDATE 29/07/06: Added a new boolean property, CacheSuggestions, which lets you choose whether to cache the suggestions on the client or not. Details in the post.
UPDATE 29/07/06: Now the controls work in conjunction with Atlas, read the post for the details.
UPDATE 08/07/06: Fixed a bug affecting the control when placed inside another WebControl.
UPDATE 05/07/06: Added a property - ScrollSize - which allows to show the results in a scrolled fashion.
UPDATE 27/06/06: Now it can be embedded into a UserControl and can retrieve the values from a UserControl method.
UPDATE 24/06/06: Fixed the bug affecting Firefox and published sources.
ScriptAculoUs
is a top quality JavaScript library, useful for everything related to
client-side web programming, like effects, DOM programming, events and
so on.
Recently they included a new "control" in the package, which
is able to extend a normal HTML input text into an autocomplete
control. Does this remind you of the Atlas autocomplete extender? Read
on...
The word "control" is not the same as the one ASP.NET
programmers are used to hear, since it now refers to a client-side
behavior, which happens completely on the client.
This autocomplete control, whom you can see examples here,
is very rich in features but not very developer-friendly from an
ASP.NET developer point of view, because almost everything has to be
programmed in the markup code and manually, so I decided to create a
custom control to wrap all those functionalities in a simple to use
component called ScriptAculoUs.Net.
But why is this better than the other thousand autocomplete controls available out there?
Well, first let me make a brief list of the ones I like most:
- Atlas Autocomplete extender: very cool, but you need a webservice to retrieve results.
- UPDATE 17/06/06: Atlas Smart Autocompletion:
a textbox built on top of Atlas framework which incorporates the Atlas autocomplete extender into a reusable web control, and enhances it by
allowing to retrieve the suggestion list from a page method other than
the classic web service method.
- Wilco Bauer's SmartTextBox: very well written webcontrol, source code is a must-see, but lacks client-side support.
- AspItalia TextBox Autocomplete: a must see too, can retrieve results from a DataSource control!
Ok, these are the coolest out there. My control can be better because:
- ScriptAculoUs is a client-side library, has great support for visual effects and the visual result is better than all of them;
- ScriptAculoUs is cross-browser, they mostly aren't;
- ScriptAculoUs is a continuous work in progress, it will improve and I won't have to care about it unless they change the API.
To sum it up, this is better because ScriptAculoUs preserves me from
caring about the client-side programming, which is the most part in an
autocomplete pattern, and provides us with a cool user interface made of fadings and scrollings (and well, much more).
Features and Usage
- No need for a web service or an external page to retrieve the
suggestions, just a page method, which has to be public, return an
object implementing the IEnumerable interface and accept a string as
input parameter (the typed keys) and/or a second array of strings parameter which contains the values of the controls specified within the property Parameters. Here is an example of how to write the method which returns the suggestions:
public string[] GetSuggestion(string key)
{
return new string[] { key + "aaa", key + "bbb", key + "ccc"};
}
In case the property Parameters contains values, the method will require a second parameter of type string[]:
public string[] GetSuggestion(string key, string[] parameters)
{
int i = parameters.Length;
return new string[] { key + parameters[0] + "aa", key + parameters[i-1] + "bb" };
}
and the markup of the page will look like the code below (the following result can be easilly achieved by using the Visual Studio designer and utilizing its straighforward collection editor):
<asp:TextBox id="TextBox1" runat="server"></asp:TextBox>
<ScriptAculoUs:AutocompleteTextBox id="AutocompleteTextBox1"
runat="server" methodname="GetSuggestions">
<Parameters>
<ScriptAculoUs:TextControlParameter ControlID="TextBox1">
</ScriptAculoUs:TextControlParameter>
</Parameters>
</ScriptAculoUs:AutocompleteTextBox>
- The support for effects, key navigation and everything related to client-side behaviors is great thanks to script.aculo.us.
- The results are cached on the client by default, so that when you type again the same characters they are retrieved by the local cache instead of performing a request to the server. Caching can be disabled using the property CacheSuggestions.
- Can be easilly configured to show an animated image next to it just
using a simple property. The image shows up when the control is
retrieving the results from the server and hides when the operation is
complete.
- Can be extended to use an AutocompleteProgress control, also
shipped, which can be placed anywhere on the page and customized using
templates, which makes its content visible when the main control is
retrieving results and makes them invisible when the callback is
complete. For those using Atlas, this is the same as the UpdateProgress
control.
- You can choose how many chars are needed to be typed before the
control performs a callback to the server. The default value is 1.
- The list of results appearance can be customized using some
style properties called Suggestionxxx and SelectedSuggestionxxx. Easy
to use.
- It is possible to scroll through the results using the ScrollSize property. It sets the height in pixels of the suggestion list area.
- UPDATE 29/07/06: The controls now do WORK in conjunction with the Atlas framework. In this post, Steve Marx describes his discovery of how Atlas and ScriptAculoUs can work together when the ScriptAculoUs scripts are injected in the page AFTER the Atlas scripts. Don't ask me why!
Since I inject the scripts programmatically in the control code (I use to do it in the PreRender phase), I have not much freedom on that, but Reflectoring the Atlas ScriptManager control I found that it injects its script during the Page PreRenderComplete event. Thus the problem turns out to be how to inject them LATER than Atlas.
As far as I know there is no event which fires after that one in which you can safely inject something in the page, so I subscribed to that event too and I did my injections there. Of course, since both Atlas and my controls inject their scripts at the same time, it becomes important the order they assume in the page. Ok, the solution is that you'll have to place your Atlas ScriptManager control BEFORE any ScriptAculoUs.Net controls, and everything will work fine! That won't be an issue I guess, since usually the ScriptManager control is placed by default on the top of the page, before any other controls.
I even played around with it a bit, and have been able to extend my AutoCompleteTextBox with the Atlas Control Toolkit's TextBoxWaterMarkExtender. Simply great. - UPDATE 19/08/06: Removed property AdditionalControl and added property Parameters. The only difference is that the Parameters property accepts a collection of values instead of only one. You can choose among the controls of the page which implement the ITextControl interface, that is, that can contain a text value. Those values are then passed to the method set with the property MethodName.
If one or more values are set in the Parameters property, then the method signature which returns the suggestion list must accept a second parameter of type string[]. - UPDATE 24/08/06: Laurentiu Macovei submitted a great contribution, here are the details:
Features added
- AutoCompleteAsHint property: for example you want to make a search form, but you
don't know what to type to get some results. This feature actually returns a set
of letters who are possible at a moment.
Eg. These are the simplified
keywords in DB: City, Police, Design, Magician and Motorcycle
If you will
type i, it will suggest you a, c, g and t. You pick one from
the list, eg. c and then it will suggest you c and e. And so on. Basically when
this feature is enabled, the suggestion is concatenated to the text, instead of
replacing the text with it.
- Ability to play with page_up, page_down, home, and end keys.
- Auto-suggest when click into the textbox.
Bugs fixed
- Annoying click on scroll (was closing the list)
- Annoying scroll into view (it didn't work, or work bad)
- Some wierd behaviour was fixed.
- Big scroll size, when not needed (now the list size adapts itself to how
much it needs, as maximum as you specifiy in the ScrollSize attribute. If not
needed, the scroll is not displayed).
I welcome any feedback and suggestion to improve it. A screencast
about how to set it up is available too. Please watch it at double
speed since it was recorded on a slow virtual machine, otherwise you
risk to fall asleep :-)
Download
Binaries: no more binaries, at the moment, too hard to keep track of them, please download the source.
Sources: only available on the SVN repository, read here for details.
Screencast: ScriptAculoUs.Net Demo.wmv

-
Lookup a control at an arbitrary level of the Page hierarchy
-
In ASP.NET 2.0 the page hierarchy often happens to be deeper than it was with the older version, mostly when using MasterPages. Consequently, when you want to obtain a reference to a control of the page given its ID and you don't know at which level of the hierarchy it is placed, using the FindControl() method of the Page object isn't the right way of proceding since it just performs a search among the direct children of the page itself.
In such cases you may use a recursive search, which walks all the page hierarchy. Note that you should use this workaround only when you strictly need it, because it could introduce a consistent overhead in the processing of the page due to the fact that everything becomes a control when on the server, and you'll find yourself looping through a considerable number of controls. This is a recursive implementation of the method:
public static Control FindControl(string controlId, ControlCollection controls)
{
foreach (Control control in controls)
{
if(control.ID == controlId)
return control;
if(control.HasControls())
{
Control nestedControl = FindControl(controlId, control.Controls);
if(nestedControl != null)
return nestedControl;
}
}
return null;
}
Then you can simply use it this way:
Control foundControl = FindControl(controlToFindID, Page.Controls);
-
The AssociatedControlID property of the Label web control
-
In ASP.NET 2.0 the Label web control exposes a new property, AssociatedControlID, which takes the ID of another control in the page, that is, a TextBox or another input control.
When the property is set, the rendering of the Label switches from a simple <span> tag to a <label> tag, whose for attribute assumes the client-side ID of the associated control as the value.
An example to clear things up
<asp:label ID="Label1" runat="server" Text="Label" />
<asp:TextBox ID="TextBox1" runat="server" />
becomes:
<span id="Label1">Label</span>
<input name="TextBox1" id="TextBox1" type="Text" />
While
<asp:label ID="Label1" AssociatedControlID="TextBox1" runat="server" Text="Label" />
<asp:TextBox ID="TextBox1" runat="server" />
becomes:
<label for="TextBox1" id="Label1">Label</label>
<input name="TextBox1" id="TextBox1" type="Text" />
The difference
The difference is an accessibility feature. Setting the
AssociatedControlID property any click on the Label extends to the
associated control. In case of an associated TextBox the effect is that
when clicking on the Label the TextBox gains focus.
-
Design resources for ASP.NET
-
I just wanted to publish a link listing of very good resources for
designing ASP.NET and non-ASP.NET websites. Includes some CSS related
content.
-
Customize control properties depending on the browser in ASP.NET 2.0
-
ASP.NET 2.0 has a nice, not much known feature which lets designer customize controls properties declaratively according to the browser requesting the page.
Let's suppose that we want to show a different Text value of a Label control depending on whether the request is coming from IE or Firefox. Then we'll just have to write something like this in the webform:
<asp:Label ID="Label1" runat="server" Text="Rendered in default browser"
ie:Text="Rendered in IE"
mozillafirefox:Text="Rendered in Firefox">
</asp:Label>
I'm pretty sure that anyone would find something more useful to apply this feature to :-)
The available browser IDs can be found in the directory %SystemRoot%\Microsoft.NET\Framework\v2.0.50727\CONFIG\Browsers