Maria globe client/Map interaction
Map utilities
The different map utilities can be turned on/off programatically e.g. through User controlls. For more details about tools and map functionality, see Map interaction client, Map_interaction and Tools interaction
Here is an example of adding check boxes with direct binding to the MariaGlobeMapControl from your main window.
...
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal"
Visibility="Visible">
<GroupBox Header="Map Utilities">
<StackPanel Orientation="Vertical" Visibility="Visible" Margin="5">
<CheckBox Content="Ruler" Margin="3"
ToolTip="Ruler"
IsChecked="{Binding IsRulerVisible, ElementName=MariaGlobeCtrl}" />
<CheckBox Content="Pan Navigation" Margin="3"
ToolTip="Pan Navigation"
IsChecked="{Binding IsPanNavigationVisible, ElementName=MariaGlobeCtrl}" />
<CheckBox Content="Scale Bar" Margin="3"
ToolTip="Center Position, Scale Bar"
IsChecked="{Binding IsScaleBarVisible, ElementName=MariaGlobeCtrl}" />
<CheckBox Content="Center Mark" Margin="3"
ToolTip="Center Position Indicator"
IsChecked="{Binding IsCenterPositionIndicatorEnabled, ElementName=MariaGlobeCtrl}" />
<CheckBox Content="Mini Map" Margin="3"
ToolTip="Mini Map"
IsChecked="{Binding IsMiniMapVisible, ElementName=MariaGlobeCtrl}" />
</StackPanel>
</GroupBox>
</StackPanel>
<Grid Grid.Row="1">
<mariaglobemapcontrol:MariaGlobeMapControl x:Name="MariaGlobeCtrl"
Background="#E9ECFA"
Layers="{Binding Layers}"
MiniMapLayer="{Binding MapViewModel.MiniMapLayer, Mode=OneWay}"
CenterScale="{Binding MapViewModel.CenterScale}"
CenterPosition="{Binding MapViewModel.CenterPosition}"
Is3DMode="False"
MouseMoveDistanceToStartTracking="0"
ZoomOnDblClick="False"
DegreeToLockRotateAndScale="2"
PercentageToLockScaleOnly="2.0"
IsRulerVisible="True"
IsCenterPositionIndicatorEnabled="True"
IsMiniMapVisible="True" />
</Grid>
</Grid>
...
Map settings
Your map service will most likely contain different map templates, and you would like to select the template to be used.
In we will create a list of templates to chose from, display the current center position and scale, and also choose the display mode - 2D or 3D.
Add the following to your Main Window XAML:
...
<GroupBox Header="Map Settings">
<Grid Margin="3">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ComboBox Name="cmbActiveMap" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Margin="0,0,0,5"
Width="Auto" Height="Auto" MinWidth="200"
VerticalAlignment="Top"
ItemsSource="{Binding MapViewModel.AvailableMapTemplateNames}"
SelectedItem="{Binding MapViewModel.ActiveMapTemplateName}"
IsSynchronizedWithCurrentItem="true" />
<Label Grid.Row="1" Grid.Column="0"
Content="Mode" FontWeight="DemiBold"/>
<StackPanel Grid.Row="1" Grid.Column="1">
<RadioButton Content="2D"
IsChecked="{Binding MapViewModel.Is2DMode, Mode=OneWay}" />
<RadioButton Content="3D"
IsChecked="{Binding MapViewModel.Is3DMode}" />
</StackPanel>
<Label Grid.Row="2" Grid.Column="0" FontWeight="DemiBold">
<TextBlock>
Center<LineBreak/>
Scale
</TextBlock>
</Label>
<TextBox Grid.Row="2" Grid.Column="1" VerticalAlignment="Center"
Text="{Binding MapViewModel.CenterScale, StringFormat=N1}"
IsReadOnly="True" />
<Label Grid.Row="3" Grid.Column="0" FontWeight="DemiBold">
<TextBlock>
Center<LineBreak/>
Position
</TextBlock>
</Label>
<TextBox Grid.Row="3" Grid.Column="1" VerticalAlignment="Center"
Text="{Binding MapViewModel.CenterPosition, Mode=OneWay}"
IsReadOnly="True" />
</Grid>
</GroupBox>
...
And bind the Is3DMode property of the MariaGlobeMapControl to same value as the Radio button.
...
<mariaglobemapcontrol:MariaGlobeMapControl x:Name="MariaGlobeCtrl" Background="#E9ECFA"
Is3DMode="{Binding MapViewModel.Is3DMode}"
Layers="{Binding Layers}"
...
Extend the MapViewModel with:
- fields and properties to handle display of available map templates and 2D/3D mode selection
- initialized event handlers with initialisation and selection of templates
- CenterPosition and CenterScale properties with notification handling.
...
private Dictionary<string, MapTemplate> _availableMapTemplateDictionary = new Dictionary<string, MapTemplate>();
private double _scale;
private GeoPos _pos;
private bool _is3DMode;
...
public bool Is2DMode { get { return !_is3DMode; } }
public bool Is3DMode
{
get { return _is3DMode; }
set
{
_is3DMode = value;
NotifyPropertyChanged(() => Is2DMode);
NotifyPropertyChanged(() => Is3DMode);
}
}
public GeoPos CenterPosition
{
get { return _pos; }
set
{
_pos = value;
NotifyPropertyChanged(() => CenterPosition);
}
}
public double CenterScale
{
get { return _scale; }
set
{
_scale = value;
NotifyPropertyChanged(() => CenterScale);
}
}
public MapViewModel(IMariaMapLayer mapLayer, IMariaMapLayer miniMapLayer)
{
_mapLayer = mapLayer;
if (_mapLayer != null)
_mapLayer.LayerInitialized += OnMapLayerInitialized;
MiniMapLayer = miniMapLayer;
if (MiniMapLayer != null)
MiniMapLayer.LayerInitialized += OnMiniMapLayerInitialized;
}
private void OnMapLayerInitialized()
{
foreach (var template in _mapLayer.ActiveMapTemplates)
{
_availableMapTemplateDictionary.Add(template.Name, template);
}
NotifyPropertyChanged(() => AvailableMapTemplateNames);
CenterPosition = new GeoPos(59.908358, 10.628190); // TPG - Lysaker
CenterScale = 3500000;
_mapLayer.ActiveMapTemplate = _mapLayer.ActiveMapTemplates.Any() ?
_mapLayer.ActiveMapTemplates.First() : null;
_mapLayer.ActiveMapTemplate = PreferredMapTemplate();
NotifyPropertyChanged(() => ActiveMapTemplateName);
}
private void OnMiniMapLayerInitialized()
{
MiniMapLayer.ActiveMapTemplate = _mapLayer.ActiveMapTemplates.Any() ?
_mapLayer.ActiveMapTemplates.First() : null;
MiniMapLayer.ActiveMapTemplate = PreferredMapTemplate();
}
public IEnumerable<string> AvailableMapTemplateNames
{
get
{
return _availableMapTemplateDictionary.Keys.ToList();
}
}
public string ActiveMapTemplateName
{
get
{
if (_mapLayer != null && _mapLayer.ActiveMapTemplate != null)
return _mapLayer.ActiveMapTemplate.Name;
return "";
}
set
{
MapTemplate template = null;
if (_availableMapTemplateDictionary.ContainsKey(value))
{
template = _availableMapTemplateDictionary[value];
}
else if (_availableMapTemplateDictionary.Any())
{
template = _availableMapTemplateDictionary.Values.First();
}
_mapLayer.ActiveMapTemplate = template;
MiniMapLayer.ActiveMapTemplate = template;
NotifyPropertyChanged(() => ActiveMapTemplateName);
}
}
private MapTemplate PreferredMapTemplate()
{
var preferred = "TOPO";
if (_availableMapTemplateDictionary.ContainsKey(preferred))
return _availableMapTemplateDictionary[preferred];
return _availableMapTemplateDictionary.Values.Any() ? _availableMapTemplateDictionary.Values.First() : null;
}
...
Running with map interaction
Running your application, observe the following:
- the map utilities are shown/hidden according to the corresponding check boxes
- the center position and scale are updated when panning/zooming the map
- the map template drop-down list contains available map templates
- the map display changes according to selected map template
- the map display changes according to deleted mode