(Click on image above to test the application - Silverlight 2, 3 or 4 runtime required)
TUTORIAL SUMMARY:
This tutorial is a bit more complex than the previous one that shows how to convert
an excel graph to an animated and dynamic graph in a Silverlight application (available
here). For this reason we will not start from stretch,
but will work with the final solution. The steps in the tutorial will explain the
main parts of the solution and how the data is prepared.
1) From Map in svg file to Silverlight
Start with original EU map in svg file. ViewerSvg is
used to convert svg file to Silverlight xaml. The Eu map is shown in a Silverlight
application (in web browser).
2) Select country on mouse over
Show the country under the mouse in other color and with thicker border.
3) Prepare country data
Get data for countries and convert them into xml. Create a CountryInfo and CountryInfoDataSource
classes to provide access to the data for the application.
4) Show country data
Show the data of the selected country.
5) Add EU countries by year slider
Add slider that will show how the EU was growing by the year.
LEVEL: Advanced
Requirements:
- Visual Studio 2008 SP1 or Visual Studio 2010
- Silverlight Tools for Visual Studio 2008 - get from Silverlight
- Get Started
- ViewerSvg with Ab2d.ReaderSvg - get from Downloads
- Microsoft Excel and Access 2007 (optional - for preparing data)
Finished sample project and sample data files are part of ViewerSvg with Ab2d.ReaderSvg package (from version 4.0 on) - see Samples\SilverlightEuPackage directory.
STEP 1
From Map in svg file to Silverlight
The source of the EU map is Wikimedia commons that, besides lots of other images, contains
also a lot of images in svg file format. The EU map we will use can be found here. The original map looks like:

The map contains EU countries colored by the year when they joined the EU. The size
of the svg file is 553 KB. If the svg file is converted to xaml it is still 280
KB. This is quite a lot for a web application. So I asked a friend, who is an export
with Adobe Illustrator, to simplify the map. He also removed the EU flag and text
and data on the left side of the image so the new svg file contains only a map of
EU. The size of the new svg file is 145 KB - this makes the size of xaml only 114
KB. This is still something, but not so much. The new file is also included in the
package: EuropeMap_simplified.svg.
Now we start ViewerSvg and open the simplified file
in it.

In the right part of the ViewerSvg a tree view is showing the structure of the read
svg file. You can see that all of the countries on the map are already named. So
if you click on the name, a country should be selected on the map. This is great
news. With this we will know on which country the mouse is. The countries are also
grouped together - the groups are named with the year when the countries in the
group joined the European Union.
Now we can export the svg file to Silverlight xaml. Click the export button. The
export dialog shows up. Select Export as Silverlight 2.0. The Root element will
be changed to Canvas. The original canvas's size is 12690 x 7959 - this is too big
for any screen resolution. So we will resize it - just enter 800 into the first
TextBox after "Resize Canvas". This will set the width of the result canvas to 800
points and the height will be automatically set to 501. To reduce the size of xaml
you can also slide the No. of decimals sliders to the left - the exported xaml will
have no decimal digits. This will make the xaml 114 KB large. Click SAVE button.
The saved xaml is used for EuMap.xaml file in the package.
With just a few clicks we have converted a map in svg file to the xaml that can
be used in Silverlight application.
STEP 2
Select country on mouse over
The code to select the countries is almost the same as with the
previous tutorial about how to create a Silverlight application from excel
graph.
This is done in code bihind file - EuMap.xaml.cs.
In the RegisterCountryEvents method the event handlers are added to the MouseEnter
and the MouseEnter event - this is recursivly done for all Path elements.
In the MouseEnter event handler the country name is get from the Path's Name. If
the name represents a country than we simply set Path's StrokeThickness and its
Fill. Than we fire a SelectedCountryChanged event to notify the parent that the
country is changed - this will be needed when we will display the country info.
In the MouseLeave event handler the path properties are set to its original values
and the SelectedCountryChanged is fired again.
STEP 3
Prepare country data
I have found data for the countries on the following site: http://www.photius.com/rankings/spreadsheets_2007/. There
are 6 excel tables with the data for all the world countries. Because I needed only
some basic data I used geography and population data only. I have also filtered
the data to the countries that are shown in the EU map. The final excel file with
the data is "eu data.xls" from the package.
Now we need to convert the data form excel file to xml file. The process is described
here. In short: the excel file is opened in Microsoft Access
and it is than saved into xml file. The EU_Data.xml contains the final countries
data. There is also EU_Data.xsd that represents the xml data schema. Both files
are also included in the Silverlight application.
Now the data needs to be imported into the application. But before this we need
a class that will hold the data. This is the CountryInfo class. Note that because
Silverlight 2 is based on .Net 3.5, it also has all the goodies of the C# for .Net
3.5. This includes Auto-Implemented Properties (the whole list can be found here) so we do not need to write all the private fields
and its properties with getters and setters, but we can simple write:
public class CountryInfo
{
public string Name { get; set; }
public int Area { get; set; }
public int Population { get; set; }
public double PopulationDensity { get; set; }
public double BirthRate { get; set; }
public double LifeExpectancy { get; set; }
}
So CountryInfo class contains properties that describe the country.
Now we need to read the data from xml to a collection of CountryInfo classes. This
is done in the CountryInfoDataSource class in its FillCountries method. The data
retrieval is done with XDocument class. This class in part of System.Xml.Linq assembly,
so we need to add reference to it. The xml file is simply loaded into the XDocument
class. The data about one country are enclosed into EU_Data elements. So we iterate
through all the EU_Data elements with a foreach. Inside the loop we simply convert
each element to its type and write it to the appropriate CountryInfo property:
// Read EU_Data.xml into XDocument
XDocument countries = XDocument.Load("EU_Data.xml");
// Go throug all the EU_Data elements
foreach (XElement oneCountryElement in countries.Descendants("EU_Data"))
{
CountryInfo oneCountry = new CountryInfo();
// Fill data
oneCountry.Name = oneCountryElement.Element("CountryName").Value;
oneCountry.Area = Int32.Parse(oneCountryElement.Element("Area").Value);
oneCountry.Population =
Int32.Parse(oneCountryElement.Element("Population").Value);
oneCountry.PopulationDensity =
double.Parse(oneCountryElement.Element("PopulationDensity").Value,
System.Globalization.CultureInfo.InvariantCulture);
oneCountry.BirthRate =
double.Parse(oneCountryElement.Element("BirthRate").Value,
System.Globalization.CultureInfo.InvariantCulture);
oneCountry.LifeExpectancy =
double.Parse(oneCountryElement.Element("LifeExpectancy").Value,
System.Globalization.CultureInfo.InvariantCulture);
_countries.Add(oneCountry.Name, oneCountry);
}
Note that this was just the most basic use of the XDocument class. The class can
be also used to create a much more complex linq quieries. Search for samples on
the net to see more.
Now it is time to show the data.
STEP 4
Show country data
The country information is shown with a CountryInfoControl user control. The simplest
way to show the data is to use the data binding and Value converters. The following
line displays the country name:
<TextBlock Grid.Column="1" Grid.Row="0" FontWeight="Bold" Text="{Binding Name}"/>
The text is simply data binded to the Name property. But where does CountryInfo
comes into the play - which Name to show?
This is done by setting the DataContext of the user control. Remember that we have
a SelectedCountryChanged event on the EuMap control. So we should subscribe to the
event and when the selected country is changed set the ContryInfoControl's DataContext
to the appropriate ContryInfo class:
// Simply just change the DataContext to the selected country info
CountryInfoCountrol.DataContext = _countriesData.GetCountry(selectedCountryName);
So we set the DataContext to the appropriate ContryInfo class. This sets the Text
properties of the TextBlocks to the value of binded property (for example Name).
This works well for strings, but numbers are not formatted well.
Solution for this is to implement a custom ValueConverter that will be used to convert
integer and double values to string with a appropriate format. This is done by the
NumberToStringConverter class. Its Convert method gets integer or double as value
and returns a formatted string. For integer values a simple format by thousands
is used. For double values an additional parameter can be used to specify number
of decimal digits. To use the converter it must be specified with the Binding settings:
<TextBlock Grid.Column="1" Grid.Row="5"
Text="{Binding LifeExpectancy,
Converter={StaticResource NumberConverter},
ConverterParameter=0}"/>
The TextBlock above shows the value of LifeExpectancy property displayed with no
decimal digits.
We also need to add the converter class to the resources of the UserControl. This
is done with firstly adding my namespace and than registering the class in the resources.
The first lines of UserControl xaml look like:
<UserControl x:Class="SilverlightEuCountries.CountryInfoControl"
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:SilverlightEuCountries"
Width="400" Height="160">
<UserControl.Resources>
<my:NumberToStringConverter x:Key="NumberConverter"/>
</UserControl.Resources>
Our user control is prepared. It can be now added to the Page.xaml.
STEP 5
Add EU countries by year slider
The original EU map contains data when the countries joined the EU. It would be
nice if the user of the application could see how the countries were joining the
EU. This could be simply done with a slider that would change the year. This step
does exaclty that.
Because the Slider control is not part of the default Silverlight assemblies, a
reference to the System.Windows.Controls.Extended must be added to the Silverlight
project.
The following xaml adds a Slider and appropriate texts to the application:
<StackPanel Orientation="Vertical" VerticalAlignment="Bottom"
HorizontalAlignment="Left" Margin="5 0 0 0">
<TextBlock FontSize="15" Margin="5 0 0 0">EU Countries by year:</TextBlock>
<StackPanel Orientation="Horizontal">
<Slider Name="EuYearSlider" Width="150" Minimum="1950" Maximum="2008"
Value="2008" SmallChange="1" ValueChanged="Slider_ValueChanged"/>
<TextBlock Name="EuYearText" FontSize="15" Margin="5 0 0 0" Text="2008"/>
</StackPanel>
</StackPanel>
The change of slider is handlered in UpdateEuForCurrentYear method. In the method
we firstly change the EuYearText Text. Than ShowEuCountriesForYear method of the
EuMap class is called.
ShowEuCountriesForYear method get a year as parameter and shows the countries that
were in the year already members of EU with its color - all other countries are
displayed with default gray color. To do this a _euYearsBrushes Dictionaries is
filled with the initial Brushes (colors) of the countries groups.
This ends this tutorial. For additional information see also the comments in the
code.
> TRY THE APPLICATION
Additional notes:
Silverlight 2 is in beta phase, so there can be some problems with it. It is also
possible that some of the classes, properties and methods will be renamed or changed
when it comes to final. So I recommend some patience when dealing with it. However
Silverlight is very good technology and will surely be a successful as it means
a giant leap ahead for online content.
|