Dec 14

The purpose of this post is to create an interactive map that allows you to select multiple regions of a map. To do this we create a customized template based on a "ToggleButton. Indeed, thanks to "ToggleButton" we're going to manage several status as "Checked" and "Unchecked" which will serve us whether the region is selected or not.
For this post we'll use a map of Belgium where you can select multiple provinces. Then, all selected provinces will be added to a list.

Step 1 Creation of template for “ToggleButton”

The first step in creating this map is to add a “ToggleButton”, then click in the list at the top left and select:

Edit Template --> Create Empty…

image

To follow the boundaries of the map we use the "Pen" to define a "Path". Since an element can be amended only by a “VisualStateGroup”, we will create 2 “Path”. One for the group “CommonStates” and one for the group “CheckStates”.

image

The 2 "Path" are identical no matter the data they contain.

<Path Fill="White" Stretch="Fill" Stroke="Black" Height="68" HorizontalAlignment="Left" Margin="35.5,24.5,0,0" VerticalAlignment="Top" Width="75" UseLayoutRounding="False" Data="M64,25 L110,55 L36,92 z"/>
<Path Fill="Black" Stretch="Fill" Stroke="Black" Height="68" HorizontalAlignment="Left" Margin="35.5,24.5,0,0" VerticalAlignment="Top" Width="75" UseLayoutRounding="False" Data="M64,25 L110,55 L36,92 z"/>

For simplicity I named the "Path", "PathCommonStates" and "PathCheckStates", and I Initialize their opacities to 0.

image

image

Then I select the path "PathCommonState" and click on the "MouseOver" state to change the opacity to 30%.

image

I do the same thing with the path "PathCheckStates", I click on "Checked" state to set the opacity to 30%.
I will then modify the code to add "TemplateBinding" properties. It gives this:

<UserControl.Resources>
	<ControlTemplate x:Key="MapButton" TargetType="ToggleButton">
		<Grid>
			<VisualStateManager.VisualStateGroups>
				<VisualStateGroup x:Name="CommonStates">
					<VisualState x:Name="Normal"/>
					<VisualState x:Name="MouseOver">
						<Storyboard>
							<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="PathCommonStates" Storyboard.TargetProperty="(UIElement.Opacity)">
								<EasingDoubleKeyFrame KeyTime="00:00:00" Value="0.3"/>
							</DoubleAnimationUsingKeyFrames>
						</Storyboard>
					</VisualState>
					<VisualState x:Name="Pressed"/>
					<VisualState x:Name="Disabled"/>
				</VisualStateGroup>
				<VisualStateGroup x:Name="CheckStates">
					<VisualState x:Name="Unchecked"/>
					<VisualState x:Name="Indeterminate"/>
					<VisualState x:Name="Checked">
						<Storyboard>
							<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="PathCheckStates" Storyboard.TargetProperty="(UIElement.Opacity)">
								<EasingDoubleKeyFrame KeyTime="00:00:00" Value="0.3"/>
							</DoubleAnimationUsingKeyFrames>
						</Storyboard>
					</VisualState>
				</VisualStateGroup>
				<VisualStateGroup x:Name="FocusStates">
					<VisualState x:Name="Unfocused"/>
					<VisualState x:Name="Focused"/>
				</VisualStateGroup>
			</VisualStateManager.VisualStateGroups>
			<Path x:Name="PathCommonStates" Opacity="0" Fill="White" Stretch="Fill" Height="{TemplateBinding Height}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" Margin="{TemplateBinding Margin}" VerticalAlignment="{TemplateBinding VerticalAlignment}" Width="{TemplateBinding Width}" UseLayoutRounding="{TemplateBinding UseLayoutRounding}" Data="{TemplateBinding Content}"/>
			<Path x:Name="PathCheckStates" Opacity="0" Fill="Black" Stretch="Fill" Height="{TemplateBinding Height}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" Margin="{TemplateBinding Margin}" VerticalAlignment="{TemplateBinding VerticalAlignment}" Width="{TemplateBinding Width}" UseLayoutRounding="{TemplateBinding UseLayoutRounding}" Data="{TemplateBinding Content}"/>
		</Grid>
	</ControlTemplate>
</UserControl.Resources>

<Grid x:Name="LayoutRoot" Background="White">
	<ToggleButton HorizontalAlignment="Left" VerticalAlignment="Top" Content="ToggleButton" Template="{StaticResource MapButton}"/>
</Grid>

Note that the property "Data" is doing a "TemplateBinding" on the property "Content". Indeed, we will use the property "Content" of "ToggleButton" to the boundaries of each region.

Step 2: Adding the map into the project


After the creation of “ToggleButton”, we will simply add the map into the project.

Step 3: Establish the boundaries of each region


The third step is creating the boundaries of each region, we will then take the "Pen" and create a "Path" point by point all around the region. Like this:

image

Then we copy all the properties of the "Path" in the customized "ToggleButton" except that "Data" property is renamed "Content" property and "Stretch" is deleted.
Example:

<Path Stretch="Fill" Height="95.333" Margin="282.667,128.5,216.667,0" VerticalAlignment="Top" UseLayoutRounding="False" Data="…"/>

Becomes:

<ToggleButton Template="{StaticResource MapButton}" Height="95.333" Margin="282.667,128.5,216.667,0" VerticalAlignment="Top" UseLayoutRounding="False" Content="…"/>

 

You can download the full code:

Tags:

Comments

Irwin Fletcher

Posted on Friday, 8 January 2010 11:51

This is a great post, it helped me get a better handle on the map application that I am messing around with.  How would you implement a zoom and pan feature with a XAML image?

Bruno Leonardo

Posted on Wednesday, 30 June 2010 14:27

What a great post! It helped me a lot!

Bruno Leonardo

Posted on Thursday, 1 July 2010 12:33

I'm having a problem when puting this to an asp page. I set the boundaries, but when I run the page, the boundarie is not aligned with my map. Could you help me solve this problem?

Houses

Posted on Wednesday, 14 July 2010 08:14

Just in case you didn't know... your site looks very peculiar in Chameleon on a Mac

Blog Literature

Posted on Thursday, 22 July 2010 16:59

I didn't use it yet but now after reading your tutorial, i am going to add it in my site. I hope it 'll be a very nice experience for me. Infact i have learn a lot from your blog. Thanks for sharing such valuable stuff with us.

Grande Dunes

Posted on Saturday, 24 July 2010 22:41

Grande Dunes

Posted on Sunday, 25 July 2010 07:37

This is one of the better blogs I have read recently

Belenda Titus

Posted on Thursday, 29 July 2010 09:37

Nice post, hopefully there will be more informative post to come. Always keep us updated.

buy yeastrol
http://www.e-yeastinfections.com/yeastrol-review

Add comment




  Country flag

biuquote
Loading