Silverlight - Creating Image Map with Hotspots
page 3 of 4
by Bryian Tan
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 30110/ 64

Putting everything together

Open Visual Studio 2008, go to File, New, Project, and choose the Silverlight Application template. If you don't have the Silverlight Controls Toolkit, you can download it from here. Make sure you have added the reference for System.Windows.Controls.Toolkit. Open the MainPage.xaml and drag a Viewbox control on to the page. This control will stretch the map image inside it proportionally when we resize the browser. Then copy the content in the MapsHotSpot.xaml into the Viewbox content in the MainPage.xaml. See below.

Listing 1

<UserControl x:Class="MapsHotspotDemo.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:controlsToolkit=
      "clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Toolkit" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480"> 
  <Grid x:Name="LayoutRoot">
        <controlsToolkit:Viewbox  x:Name="MapsViewbox"  >
<!-- Maps content here -->
               <Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
                    x:Name="MapsHotSpot" Width="800" 
                    Height="600" Clip="F1 M 0,0L 800,0L 800,600L 0,600L 0,0" 
                    UseLayoutRounding="False">
                  ...
               </Canvas>
<!-- End Maps content here -->
        </controlsToolkit:Viewbox>
  </Grid>
</UserControl>
 

Expression Blend

If you choose to do it by using Expression Blend, here are the steps to follow.

1.    Open Microsoft Expression Blend.

2.    Click on File, select New Project and follow the setup from below.

Figure 7

Add a Viewbox into the LayoutRoot and name it MapsViewbox, then add a Canvas inside the Viewbox and name it MapsHotspot. After that, add a Canvas into MapsHotspot and an Image control into the Canvas. From the Image control properties, specify the image source and setup the appropriate width and height of the image. Then, create another Canvas and name it Russia or something meaningful or unique. Make sure that the width and height of the newly created Canvas match the image in order to draw points on it. Click on the Pen tool and draw points or vertices around Russia. Pick a brush color and set it Opacity to certain percentages. Repeat the same procedure for the rest of the countries.

Figure 8

Tooltips

Remember that we named each layer at the beginning. The layers and points are translated into Canvas and Path objects respectively when we export them into XAML. We can provide each layer with a unique name or include a tag attribute to it and use it to pull the country information from a database or resource dictionaries. For simplification sake, we will have a method to loop through each child elements in the MapsHotSpot Canvas, grab their name and set it to the tooltip content. Attach a MouseMove event to each layer to highlight the country on mouse hover. Also, attach a MouseLeftButtonUp event to pop up a menu when the left mouse button is released. See Listing 2.

Listing 2

foreach (Canvas c in (this.FindName("MapsHotSpot"as Canvas).Children)
            {
                if (!string.IsNullOrEmpty(c.Name))
                {
                    c.Cursor = Cursors.Hand;
                    ToolTip toolTip = new ToolTip { Content = c.Name };
                    c.SetValue(ToolTipService.ToolTipProperty, toolTip);
 
      c.MouseMove += new MouseEventHandler(c_MouseMove);
                    c.MouseLeftButtonUp += new                    
                        MouseButtonEventHandler(c_MouseLeftButtonUp);
                }
            }

Displayed below is the implementation of the c_MouseMove method. This method will highlight the Canvas/ country and clear the previous selection, if there is any, during mouse hover event. 

Listing 3

void c_MouseMove(object sender, MouseEventArgs e)
        {
            Canvas c = sender as Canvas;
            ResetLastSelected();
 
            if (!string.IsNullOrEmpty(c.Name))
            {
                lastSelected = c.Name;
                SetCanvasColor(c, Color.FromArgb(255, 92, 112, 171), 2, Colors.Green);
            }
        }

View in browser, you should see something like below. If you resize the browser, you will still see the full map. Place the mouse over the map image to see the tooltip and the highlighted region.

Figure 9

<img border=0 width=450 height=441 src="/ArticleFiles/1913/image010.gif">
 

We will build a simple menu with several links in it. First, add a simple class to hold the link properties. See below for an example.

Listing 4

    public class Links
    {
        public string Title { get; set; }
        public string URL { get; set; }
 
        public Links(string t, string u)
        {
            Title = t;
            URL = u;
        }
    }

After that, create a global List (T) class to hold the link objects and populates the link class with the below data on page load.

Listing 5

private List<Links> _links = new List<Links>();
 
void SetupLinks()
        {
            _links.Add(new Links("About the people", 
                  "http://www.countryreports.org/{0}.aspx"));
            _links.Add(new Links("Economy", "http://www.economicexpert.com/a/{0}.htm"));
            _links.Add(new Links("Global Statistics", 
                  "http://www.geohive.com/cntry/{0}.aspx"));
            _links.Add(new Links("Population", 
                  "http://www.geohive.com/charts/population1.aspx"));
            _links.Add(new Links("Wiki""http://en.wikipedia.org/wiki/{0}"));
        }

Below is the implementation of the c_MouseLeftButtonUp method. This method will bring up the popup menu by calling the PopulateContextMenu method in response to the mouse left button click event. The PopulateContextMenu take a country name as an argument, loop through the list of link objects and concatenate the country name to it. The purpose of the PositionContextMenu method is to set the popup menu position. I also added animation to fade in and fade out the popup menu, please refer to the MainPage.xaml.

Listing 6

void c_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            Canvas c = sender as Canvas;
            if (!string.IsNullOrEmpty(c.Name))
            {
                PopulateContextMenu(c.Name);
                PositionContextMenu(e.GetPosition(contextMenu.Parent as UIElement),
                    true);
                e.Handled = true;
            }
        }
 
        void PositionContextMenu(Point p, bool useTransition)
        {
            if (useTransition)
                contextMenu.IsOpen = false;
            contextMenu.HorizontalOffset = p.X;
            contextMenu.VerticalOffset = p.Y;
            contextMenu.IsOpen = true;
        }
 
void PopulateContextMenu(string country)
        {
            contextListBox.Items.Clear();
 
            foreach (Links l in _links)
            {
                HyperlinkButton hlb = new HyperlinkButton();
                hlb.Content = l.Title;
                hlb.NavigateUri = new Uri(string.Format(l.URL, country));
                hlb.TargetName = "_blank";
 
                contextListBox.Items.Add(hlb);
            }   
        }

 

At this point, you should see something like below.

Figure 10

The final piece is to hide the popup menu and clear the highlighted country once we click on the non- clickable area of the map image. In order to achieve that, we can attach a MouseLeftButtonUp event to the Layout grid on page load. See below.

Listing 7

LayoutRoot.MouseLeftButtonUp += new MouseButtonEventHandler(LayoutRoot_MouseLeftButtonUp);
 
void LayoutRoot_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {      
            ResetLastSelected();
            HideMenu();
        }
 
        void HideMenu()
        {
            HidePopup.Begin();
            contextMenu.HorizontalOffset = -50.0;
        }

 

Points of Interest

Initially I was planning to use the right mouse button click event class that I found from here to trigger the popup menu, but I decided to leave it out after reading an article from here about its disadvantages.

I found this article useful although it was written in VB.NET and I can't get it to compile, but I'm able to utilize the logic embedded in it.


View Entire Article

User Comments

No comments posted yet.






Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2021 ASPAlliance.com  |  Page Processed at 2021-04-13 12:32:54 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search