(Not Signed In)

Sign In

Resources

Controlling a SilverStream map using data-bound controls

This tutorial will demonstrate the use of data-binding and various map controls to pan and zoom a map. The controls include buttons, a slider and a checkbox. This tutorial is one of many Telogis SilverStream tutorials.

This guide is broken into the following four steps:

  1. Create a Visual Studio project
  2. Configure a GeoStream server using C# code
  3. Add a map, zoom buttons, zoom slider, pan buttons, and a checkbox using XAML code
  4. Implement the behaviour of the zoom and pan controls using C# code

Create a Silverlight project and configure a GeoStream server

First, make sure that the file clientaccesspolicy.xml is installed in your Inetpub\wwwroot folder. Create a new Silverlight project named 'MapControlsTutorial' and add a reference to Telogis.GeoBase.SilverStream.dll. Configure a GeoStream server.

See the Create a SilverStream-Specific Visual Studio Project tutorial for an illustrated walk-through.

Add user controls

Open MainPage.xaml and add the following attributes to the UserControl tag. These attributes allow your XAML code to access the local namespace (MapControlsTutorial) and the Telogis.GeoBase namespace.

xmlns:Local="clr-namespace:MapControlsTutorial"
xmlns:GeoBase="clr-namespace:Telogis.GeoBase;assembly=Telogis.GeoBase.Silverlight"

Before the Grid tags, add the following UserControl element which references the IntegerToDouble class. This class, which implements the IValueConverter interface, provides "integer to double", and "double to integer" methods which are used with binding the slider control value to that of the zoom level.

<UserControl.Resources>
  <Local:IntegerToDouble x:Key="intToDouble" />
</UserControl.Resources>

The following code snippets should be placed between the Grid tags.

We'll begin by creating the rows, and adding the map to row 0:

<Grid.RowDefinitions>
  <RowDefinition Height="400" />
  <RowDefinition Height="30" />
  <RowDefinition Height="80" />
  <RowDefinition Height="30" />
  <RowDefinition Height="30" />
  <RowDefinition Height="*" />
</Grid.RowDefinitions>

<Border BorderBrush="Black" Grid.Row="0" BorderThickness="2">
  <GeoBase:Map x:Name="MainMap" Center="36,-120" Zoom="4" />
</Border>

Next, we'll add the zoom buttons, and the zoom slider to row 1. The zoom buttons are assigned to event handlers (Plus_Click() and Minus_Click()) that we'll create in the C# code. Notice also that the slider value is bound to the Zoom property.

<StackPanel Orientation="Horizontal" Grid.Row="1">
  <Button x:Name="btnPlus"
          Content="+"
          Width="30"
          Height="30"
          Click="Plus_Click"></Button>
  <Button x:Name="btnMinus"
          Content="-"
          Width="30"
          Height="30"
          Click="Minus_Click"></Button>
  <Slider x:Name="sldrZoom"
          Width="200"
          Margin="10,0,0,0"
          Maximum="17"
          Minimum="1"
          SmallChange="1"
          LargeChange="2"
          Value="{Binding Zoom, ElementName=MainMap, Mode=TwoWay,Converter={StaticResource intToDouble}}" />
  </StackPanel>

Next, we'll add the panning buttons (N,E,W, and S) to row 2. Again, the functionality of these controls are dealt with in the C# event handlers: btnUp_Click(), btnDown_Click(), btnLeft_Click() and btnRight_Click().

<StackPanel Orientation="Horizontal" Grid.Row="2" Grid.RowSpan="2">
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="20" />
      <RowDefinition Height="20" />
      <RowDefinition Height="20" />
      <RowDefinition Height="20" />
    </Grid.RowDefinitions>

    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="20" />
      <ColumnDefinition Width="20" />
      <ColumnDefinition Width="20" />
      <ColumnDefinition Width="20" />
      <ColumnDefinition Width="20" />
      <ColumnDefinition Width="20" />
    </Grid.ColumnDefinitions>

    <RepeatButton x:Name="btnUp"
                  Content="N"
                  Grid.Row="0"
                  Grid.Column="2"
                  Grid.RowSpan="2"
                  Grid.ColumnSpan="2"
                  Click="btnUp_Click" />

    <RepeatButton x:Name="btnDown"
                  Content="S"
                  Grid.Row="2"
                  Grid.Column="2"
                  Grid.RowSpan="2"
                  Grid.ColumnSpan="2"
                  Click="btnDown_Click" />

    <RepeatButton x:Name="btnLeft"
                  Content="E"
                  Grid.Row="1"
                  Grid.Column="0"
                  Grid.RowSpan="2"
                  Grid.ColumnSpan="2"
                  Click="btnLeft_Click" />

    <RepeatButton x:Name="btnRight"
                  Content="W"
                  Grid.Row="1"
                  Grid.Column="4"
                  Grid.RowSpan="2"
                  Grid.ColumnSpan="2"
                  Click="btnRight_Click" />
  </Grid>

</StackPanel>

Finally, we'll add the check box. If the check box is checked the map stops responding to mouse events, but can still be manipulated by the controls. This behavior is achieved simply by binding the checkbox's IsChecked property to the Map object's LockMap property.

<StackPanel Orientation="Horizontal" Grid.Row="3">
  <TextBlock VerticalAlignment="Center">Lock Map</TextBlock>
  <CheckBox VerticalAlignment="Center"
             IsChecked="{Binding LockMap, ElementName=MainMap, Mode=TwoWay}" />
</StackPanel>
<TextBlock Grid.Row="4"  VerticalAlignment="Center">
  Lock Map prevents the map from responding to mouse events, 
  but still allows controls to manipulate the map.
</TextBlock>

Implementing behavior using C# code

Open MainPage.xaml.cs and add the following using statements:

using System.Windows.Data;
using Telogis.GeoBase;
using Telogis.GeoBase.GeoStream;

Inside the MainPage class, insert the following code:

Point MapCenter;

// zoom the map out when the minus button is clicked
private void Minus_Click(object sender, RoutedEventArgs e) {
  MainMap.Zoom--;
}

// zoom the map in when the plus button is clicked
private void Plus_Click(object sender, RoutedEventArgs e) {
  MainMap.Zoom++;
}

// pan the map north when the N button is clicked
private void btnUp_Click(object sender, RoutedEventArgs e) {
  MapCenter = MainMap.LatLonToXYOverlay(MainMap.Center);
  MainMap.Center = MainMap.XYOverlaytoLatLon(new Point(MapCenter.X, MapCenter.Y - 5));
}

// pan the map south when the S button is clicked
private void btnDown_Click(object sender, RoutedEventArgs e) {
  MapCenter = MainMap.LatLonToXYOverlay(MainMap.Center);
  MainMap.Center = MainMap.XYOverlaytoLatLon(new Point(MapCenter.X, MapCenter.Y + 5));
}

// pan the map west when the W button is clicked
private void btnLeft_Click(object sender, RoutedEventArgs e) {
  MapCenter = MainMap.LatLonToXYOverlay(MainMap.Center);
  MainMap.Center = MainMap.XYOverlaytoLatLon(new Point(MapCenter.X - 5, MapCenter.Y));
}

// pan the map east when the E button is clicked
private void btnRight_Click(object sender, RoutedEventArgs e) {
  MapCenter = MainMap.LatLonToXYOverlay(MainMap.Center);
  MainMap.Center = MainMap.XYOverlaytoLatLon(new Point(MapCenter.X + 5, MapCenter.Y));
}

Finally, add the IntegerToDouble class. This class is used to convert between the integer Map Zoom value and the double Slider value.

public class IntegerToDouble : IValueConverter
{
#region IValueConverter Members
  // int to double
  public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture){
    int x = (int)value;
    double y = (double)x;
    return y;
  }

  // double to int
  public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture){
    int foo = (int)Math.Round((double)value);
    return foo;
  }
#endregion
}

Testing

Press F5 to build and run your application. Your default web browser will load a web page displaying a map and some user controls. Use the controls to zoom and pan the map.

Next step

The next tutorial, Displaying SilverStream map information, demonstrates how to display information about the map (such as the current zoom level, the map coordinates under the mouse cursor and other GeoStream information). Alternatively you can skip ahead to another Telogis SilverStream tutorial.

Published, Jun 28th, 15:39

Tagged under: silverlight maps