воскресенье, 27 июля 2014 г.

Manco Shapefile Editor - Integration with Telerik RadMap control for WPF


The projects are created in the Manco Shapefile Editor can be easily loaded into the Telerik RadMap control with just few lines of code.

You may ask why this is necessary. The Telerik RadMap control can load ESRI shape files and KML files. The Manco Shapefile Editor can export shapes into these formats. So at the first glance we need not this extra functionality. But think about following:
  1. The figures in the ESRI shape file format are represented by polylines and polygons. So every curve (ellipse, arc, Bezier curve and so on) created in the editor should be interpolated using polygons. It increases significantly number of the points are used to represent every shape and, as result, increase initial loading time, slowdown zooming in the RadMap, and makes curves look like polygon after some zoom level. In contrast any figures in the Manco Shapefile Editor project can be represented directly using correspondent map shapes in the Telerik RadMap control. So no interpolation is needed to represent shapes. It makes curves look absolutely same way as they were designed in the editor.
  2. Using this feature you can not only load the shapes, but open correspondent map provider and load background images (when necessary) automatically
So this feature significantly simplifies process of the creation applications using Telerik RadMap control and makes resulting picture much better.

To do it:

  1. Create new WPF application.
  2. Add references for the RadMap control:
  3. Add RadBusyIndicator, RadMap control and button to load project into your XAML. Setup bindings for the map properties:<Window x:Class="TestWpfApplication.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
        Title="MainWindow"
        Height="520" Width="650">
        <telerik:RadBusyIndicator Name="busyIndicator">
           <Grid>
              <Grid.ColumnDefinitions>
                 <ColumnDefinition Width="*" />
                 <ColumnDefinition Width="Auto" />
              </Grid.ColumnDefinitions>
              <telerik:RadMap Name="radMap"
                 Provider="{Binding Provider}"
                 Center="{Binding Center, Mode=TwoWay}"
                 ZoomLevel="{Binding ZoomLevel, Mode=TwoWay}"
                 MouseClickMode="SelectItem"
                 MouseSelectionMode="RaiseEvent" />
              <Button Grid.Column="1"
                 Click="OnButtonClick"
                 VerticalAlignment="Top"
                 HorizontalAlignment="Stretch">
                 <TextBlock Margin="4,2,4,2" Text="Load project" />
              </Button>
           </Grid>
        </telerik:RadBusyIndicator>
    </Window>
  4. Add reference to the Manco.MapShapeData.Load.dll.
  5. If you are using newer version of the Telerik RadControls for WPF than it was used to build Manco.MapShapeData.Load .dll then redirect assembly versions for Telerik assemblies as it is described here.
  6. Add code which load project file and bind it to the RadMap control:
C#

private async void OnButtonClick(object sender, RoutedEventArgs e)
{
   OpenFileDialog openProjectDialog = new OpenFileDialog();
   openProjectDialog.Filter = "ShapeFileEditor Project Files|*.shprj";
   openProjectDialog.Multiselect = false;

   bool? open = openProjectDialog.ShowDialog();
   if (open == true && !string.IsNullOrEmpty(openProjectDialog.FileName))
   {
      await this.LoadProject(
         new Uri(openProjectDialog.FileName, UriKind.RelativeOrAbsolute));
   }
}

private async Task LoadProject(Uri projectUri)
{
   this.busyIndicator.IsIndeterminate = true;
   this.busyIndicator.IsBusy = true;

   ProjectInfo info = await ProjectReader.Read(projectUri, this.Dispatcher);
   this.BindProject(info);

   this.busyIndicator.IsBusy = false;
}

private void BindProject(ProjectInfo info)
{
   if (info != null)
   {
      if (info.Errors.Count == 0)
      {
         ProjectReader.CreateLayers(
            this.radMap,
            info,
            this.Resources["PointDataTemplate"] as DataTemplate,
            null);
         this.radMap.DataContext = info;
      }
   }
}


VB.NET


Private Sub OnButtonClick(sender As Object, e As RoutedEventArgs)
    Dim openProjectDialog As New OpenFileDialog()
    openProjectDialog.Filter = "ShapeFileEditor Project Files|*.shprj"
    openProjectDialog.Multiselect = False

    Dim open As System.Nullable(Of Boolean) = openProjectDialog.ShowDialog()

    If open = True AndAlso Not String.IsNullOrEmpty(openProjectDialog.FileName) Then
        Await Me.LoadProject(New Uri(openProjectDialog.FileName, UriKind.RelativeOrAbsolute))
    End If
End Sub

Private Function LoadProject(projectUri As Uri) As Task
    Me.busyIndicator.IsIndeterminate = True
    Me.busyIndicator.IsBusy = True

    Dim info As ProjectInfo = Await ProjectReader.Read(projectUri, Me.Dispatcher)
    Me.BindProject(info)

    Me.busyIndicator.IsBusy = False
End Function

Private Sub BindProject(info As ProjectInfo)
    If info IsNot Nothing Then
        If info.Errors.Count = 0 Then
            ProjectReader.CreateLayers(Me.radMap, _
               info, _
               TryCast(Me.Resources("PointDataTemplate"), DataTemplate), Nothing)
            Me.radMap.DataContext = info
        End If
    End If
End Sub


You can find sample solution which implements this approach on our official site at the http://www.mancosoftware.com/ShapeFileEditor/download.htm