Building a Store Locator ASP.NET Application Using Google Maps API (Part 3)By Scott Mitchell
Over the past two weeks I've showed how to build a store locator application using ASP.NET and the free Google Maps API and Google's geocoding service. Part 1 looked at creating the database to record the store locations. This database contains a table named
Storeswith columns capturing each store's address and latitude and longitude coordinates. Part 1 also showed how to use Google's geocoding service to translate a user-entered address into latitude and longitude coordinates, which could then be used to retrieve and display those stores within (roughly) a 15 mile area. At the end of Part 1, the results page listed the nearby stores in a grid. In Part 2 we used the Google Maps API to add an interactive map to the search results page, with each nearby store displayed on the map as a marker.
The map added in Part 2 certainly improves the search results page, but the way the nearby stores are displayed on the map leaves a bit to be desired. For starters, each nearby store is displayed on the map using the same marker icon, namely a red pushpin. This makes it difficult to match up the nearby stores listed in the grid with those displayed on the map. Hovering the mouse over a marker on the map displays the store number in a tooltip, but ideally a user could click a marker to see more detailed information about the store, such as its address, phone number, a photo of the storefront, and so forth.
This third and final installment shows how to enhance the map created in Part 2. Specifically, we'll see how to customize the marker icons displayed in the map to make it easier to identify which marker corresponds to which nearby store location. We'll also look at adding rich popup windows to each marker, which includes detailed store information and can be updated further to include pictures and other HTML content. Read on to learn more!
Displaying Custom Marker Icons in a Map
As we saw in Part 2, adding a marker to a map can be accomplished using the
Note that the
Marker object's constructor is passed an object that contains a variety of properties. In the above snippet of code two options are specified:
position. These are but two of the several options available. (See the
object specification for a complete list.) Another option is the marker's icon setting, which can be customized by specifying the URL of an image to display
for the marker. For example, if we had an image file on our web server in the
Images folder named
StarIcon.png we could have that image
To make it easier for the user to determine which store listed in the grid corresponds with which store in the map, let's have each marker on the map use a different icon. Specifically, let's have each store location use an icon numbered 1, 2, 3, and so on. We can then show this same icon in the grid. The screen shot below illustrates this concept. Note how the four locations on the map are identified by icons numbered 1 through 4, and the results in the grid are also numbered 1 through 4. This approach makes it easy to identify what stores in the grid correspond to what stores on the map.
Generating the Custom Marker Icons
This simplest way to display such numeric icons would be to create a series of image files named
2.png, and so on, up to perhaps
50.png(or whatever the maximum number of store locations are within a 15 mile area of one another). Each image would be a 20x20 pixel image with the appropriate number. Rather than create these 50 images, I decided instead to generate the images dynamically using the GeneratedImage Web control available from the official ASP.NET CodePlex project. The GeneratedImage control simplifies creating and serving dynamically-generated images from an ASP.NET website; this control was discussed in detail in a previous 4Guys article, Dynamically Generating and Caching Images in ASP.NET with the GeneratedImage Control.
The download available at the end of this article includes the
Microsoft.Web.GeneratedImage.dll assembly in the
Bin folder, which you'll need
to use the GeneratedImage control. It also implements the HTTP Handler that is responsible for actually generating the image,
is in the
Images folder. In a nutshell, visiting the URL
Images/NumberToImageHandler.ashx?number=number generates a PNG image that has
a navy circle with white text showing the number number. For example, the image shown below is what is generated by
visiting the URL
Examining the code for the
NumberToImageHandler.ashx HTTP Handler would take us a bit off course, so I'm going to pass on exploring this handler further.
For more information, download the demo available at the end of this article (which includes both C# and VB code) and read the Dynamically
Generating and Caching Images in ASP.NET with the GeneratedImage Control article.
|A Word On Dynamically-Generating Images...|
While the custom marker icons can certainly be generated dynamically as I've done in this demo, for a real-world project I'd strongly suggest creating static images
for each of the possible icons (|
Updating the Results Page to Use Custom Marker Icons
Now that we have a mechanism to generate a custom marker icon for each search result, the final piece of the puzzle is to update the search results page to use these custom marker icons. This involves two steps. First, we must update the ListView control in the search results page to include the appropriate icon next to the address of each result. This is accomplished by adding the following markup to the ListView's ItemTemplate:
The highlighted markup shows the databinding syntax that assigns the Image control's
ImageUrl property to the appropriate
URL. Specifically, the
ImageUrl property is set to
~/Images/NumberToImageHandlerCS.ashx?number=number, where number is the
current index of the item being rendered in the ListView plus 1. Understand that each item in the ListView has an associated
DisplayIndex that indicates the
position of the item in the collection of items. The first ListView item has a
DisplayIndex of 0, the second of 1, and so on. The net result is that
the first result in the ListView will display the 1 icon, the second the 2 icon, and so forth.
The final step is to update the markers in the map to display the appropriate icon. In Part 2 we
added code to the search results page's
init_map function, which
displays the map and adds the markers.
To specify the custom marker icons we need to update the server-side code that generates the array of marker options. Specifically, we need to update it to include the
icon property. The following code snippet shows this addition. The
foreach loop enumerates the search results and for each nearby store the
marker options are created. The only difference in the code below from the code we created in Part 2 is the inclusion of the
icon property, which
uses the URL
Images/NumberToImageHandler.ashx?number=number, where number is the index of the result plus 1. (Note: to see the VB
version of this code please download the demo.)
And that's all there is to it! With the additions to the ListView's ItemTemplate and the
Page_Load event handler the grid and map now show numbered icons
rather than the standard pushpin icon, thereby making it easier for visitors to match store locations listed in the grid with the store location displayed on the map.
Displaying an Info Window When Clicking a Marker in the Map
If the user hovers her mouse over a map marker, the browser displays a tooltip that contains the marker's title (Store #NNN, in this case). It would be nice to display rich, detailed store information, including the store's address and perhaps a picture of the storefront. This is possible through the use of info windows, which are windows that display content in a floating window above the map. If you've used Google Maps in the past you've certainly seen and experienced info windows. They are the white, balloon windows that appear over a marker when you click it.
Displaying an info window when clicking a marker involves two steps:
- Creating the info window by instantiating an
- Displaying the info window when the marker is clicked.
infothat displays the text "Hello, world" within an
h3element. Next, a client-side
clickevent handler is created for the marker named
marker, which displays the info window affixed to the clicked marker.
init_map that is responsible for displaying the map and adding the markers to it. To display
info windows with each marker we need to beef up this function so that it can be passed an array of info window content (the message to show in each info window).
Then, for each marker we add a new
InfoWindow object and create a
click event handler for the marker to display its associated
Here is an abbreviated form of the
init_map function highlighting the new functionality for creating an info window for each marker and displaying the
appropriate window when the user clicks the marker. The additions made since Part 2 are highlighted.
Note that the
init_map function accepts a new input parameter,
infoWindowContents, which is an array of info window content. This
array is created and supplied to the
init_map function in the search result page's
Page_Load event handler (in the same loop where the
been removed for brevity.
Each store's info window displays the store number (in bold) along with the address. To show more information or to modify the style of the text in the info window, simply
modify the HTML assigned to the
init_map function when the page is loaded.
(See the call to the
ClientScript.RegisterStartupScript method at the end of the
Page_Load event handler.)
With the above code in place, users can now click markers to display information about the corresponding store. The screen shot below show the map after the user has clicked the info window for Store #847. Pretty neat!