Runtime Extensibility Framework

For Runtime .NET 100.3

Updated: 2018-08-09

The Runtime Extensibility Framework is a simple, open-source component that enables development of extensible, configurable, MVVM applications using the ArcGIS Runtime .NET SDK. Emphasis is placed on the following concepts:

RTReader, available for download, provides not only a ready-to-use application, but also an example of configuring and supporting the Extensibility Framework. This documentation will draw primarily upon it for examples.

Supporting the Extensibility Framework

In order to support the Extensibility Framework, a class in the application (typically the MainWindow class) must implement the IMainWindow interface:

When the application launches, the main window initializes the Extensibility Framework by initializing the MapApplication object as follows:


MapApplication.Init(pMainWindow);

where pMainWindow is an instance of a class that implements IMainWindow. If the argument is null, MapApplication checks the application main window to see if it implements IMainWindow.

The MapApplication class also exposes the following members:

The MainLayoutModel is the master data context for the UI of the main window. It exposes the following members for binding:

The AppViewExt class is the default view extension; it provides an entry point to the map and manages tool registration and activation. It exposes the following members:

Three subfolders are expected to exist under the application executable, or else to be created and populated from corresponding subfolders under the folder defined by the UpdateLocation property:

Note that view and extension assemblies must have unique names. A view assembly cannot have the same name as an extension assembly.

The main layout in a view library is a UserControl which is declared in the configuration file (see below). Controls in the layout bind their data contexts to the DataContexts[KEY] property, where the key is a model extension provided by an extension class library. Here is an example of a typical tool button:


<RadioButton

   DataContext="{Binding DataContexts[QueryAddin.QueryTools]}"

   Command="{Binding IdentifyCommand}"

   ToolTip="Identify"

   Style="{StaticResource LayoutToolStyle}"

   IsChecked="{Binding IdentifyToolChecked}">

   <Image

      Source="Images/Identify.png"

      Style="{StaticResource LayoutIconStyle}"/>

</RadioButton>

Also, a ContentPresenter control binds its Content property to the MapViewContainerContent property, which is an instance of the MapView control. Multiple MapViews are currently not supported.


<ContentPresenter

   Grid.Column="1"

   Content="{Binding MapViewContainerContent}" />

The following is a list of interfaces to be implemented by the developer:

Various helper classes also exist for the benefit of the developer:

The Configuration File

The configuration file is named after the Configuration property (plus an .xml extension). [See the configuration file for RTReader for an example.] There are two main sections in the configuration file: "MainLayout" and "Extensions".

The "MainLayout" section contains the application title, the name of view assembly containing the main UI, and the name of the main UI class in the view assembly. [All UIs defining the main application and any child windows are expected to be subclasses of UserControl.] In addition, nonmodal child dialogs may be defined as instances of the ChildWindow or ChildItem class. ChildItems are typically panes in a multipane control such as a TabControl.

Here is an example MainLayout configuration:




   <MainLayout>

      <Title>FieldApp - Gas</Title>

      <ViewAssembly>TabletViews</ViewAssembly>

      <MainLayoutName>MainLayout</MainLayoutName>

      <NonModalChild>ChildItem</NonModalChild>

      <ShowChildItemIcon>True</ShowChildItemIcon>

      <ShowChildItemTitle>False</ShowChildItemTitle>

   </MainLayout>



The "Extensions" section contains the declaration and configuration for each extension to be used in the application. Each "Extension" entry can have the following (optional) sections: Model extensions and view extensions may optionally implement the IConfigurable interface. In that case, a "ConfigData" section in the XML configuration provides a string which may be parsed appropriately by the extension upon loading.

Core Extensions

In addition to the main Extensibility component, code is also provided for several core extensions. Binaries are only provided for those extensions that are used in RTReader (NavAddin and QueryAddin). It is up to the developer to compile the other extensions.

NavAddin

Provides support for map navigation, opening Runtime content, table of contents, map copy/export, and GPS location display.

The following commands are exposed to the UI:

Data Context KeyCommand
NavAddin.NavCommandsOpenMapCommand
NavAddin.NavCommandsExportMapCommand
NavAddin.NavCommandsCopyMapCommand
NavAddin.NavCommandsUserSettingsCommand
NavAddin.NavCommandsZoomInFixedCommand
NavAddin.NavCommandsZoomOutFixedCommand
NavAddin.NavCommandsZoomFullCommand
NavAddin.NavCommandsZoomPrevCommand
NavAddin.NavCommandsZoomNextCommand
NavAddin.NavCommandsGPSCommand
NavAddin.NavCommandsShowTOCCommand
NavAddin.NavCommandsHideTOCCommand
NavAddin.NavCommandsExitCommand
NavAddin.NavModelExtScaleEnteredCommand
NavAddin.NavToolsZoomInCommand
NavAddin.NavToolsZoomOutCommand
NavAddin.NavToolsPanCommand

The following bindable properties are also exposed:

Data Context KeyPropertyType
NavAddin.MapModelExtTOCObservableCollection<TocDataItem>
NavAddin.MapModelExtStatusTextstring
NavAddin.MapModelExtCoordinateTextstring
NavAddin.MapModelExtProgressVisibilityVisibility
NavAddin.NavCommandsGPSVisibilityVisibility
NavAddin.NavModelExtMapReadybool
NavAddin.NavModelExtScaleItemsSourceObservableCollection<string>
NavAddin.NavModelExtScaleSelectedIndexint
NavAddin.NavModelExtScaleVisibilityVisibility
NavAddin.NavModelExtIsScaleVisiblebool
NavAddin.NavModelExtScaleTextstring
NavAddin.NavToolsZoomInToolCheckedbool
NavAddin.NavToolsZoomInToolCheckedbool
NavAddin.NavToolsPanToolCheckedbool

The following views are expected to exist in the referenced view library:

The "ConfigData" section for the MapModelExt model extension can have the following (optional) entries:

Here are some example entries:


   <Map Type="SimpleTestMap" />

   <Map Type="BasicMap" Background="#FFF0F0F0" MaxScale="10" Extent="231000, 10986000, 2482000, 13835000">

      <TileCacheLayer Path="C:\apps\FieldApp\Data\uesg_cache" DisplayName="AZ Imagery" IsVisible="False" />

      <TileCacheLayer Path="C:\apps\FieldApp\Data\AZGasSplashScreen.tpk" DisplayName="Splash Screen" MaxScale="500000" />

      <MobileMapPackageLayer DisplayName="AZ Landbase" Path="C:\apps\FieldApp\Data\AZLandbase.mmpk" MapIndex="0" IsExpanded="False" />

      <MobileMapPackageLayer DisplayName="AZ Gas" Path="C:\apps\FieldApp\Data\AZGas.mmpk" MapIndex="0" IsExpanded="True">

         <Group DisplayName="Gas Customers" IsExpanded="True">

            <FeatureLayer Name="Premise" />

            <FeatureLayer Name="Meter Setting" />

         </Group>

         <Group DisplayName="Gas Facilities" IsExpanded="True">

            <FeatureLayer Name="Controllable Fitting" />

            <FeatureLayer Name="Non-Controllable Fitting" />

            <FeatureLayer Name="Main Job Separator" />

            <FeatureLayer Name="Leak Location" />

            <FeatureLayer Name="Drisco Inspection" />

            <FeatureLayer Name="Locate Ball" />

            <FeatureLayer Name="Gas Valve" />

            <FeatureLayer Name="Relief Valve" />

            <FeatureLayer Name="Excess Flow Valve" />

            <FeatureLayer Name="Regulator & Town Border Station" />

            <FeatureLayer Name="Rural Tap" />

            <FeatureLayer Name="Point of Custody" />

            <FeatureLayer Name="Service" />

            <FeatureLayer Name="Service Sleeve" />

            <FeatureLayer Name="CP Bond Wire" />

            <FeatureLayer Name="Distribution Main" />

            <FeatureLayer Name="High Pressure Distribution Main" />

            <FeatureLayer Name="Transmission Main" />

            <Group DisplayName="Abandoned Gas Pipe">

               <FeatureLayer Name="Abandoned Service" />

               <FeatureLayer Name="Abandoned Distribution Main" />

               <FeatureLayer Name="Abandoned High Pressure Distribution Main" />

               <FeatureLayer Name="Abandoned Transmission Main" />

            </Group>

         </Group>

         <Group DisplayName="CP Objects">

            <FeatureLayer Name="Casing" />

            <FeatureLayer Name="CP Bond" />

            <FeatureLayer Name="CP Insulated Facility" />

            <FeatureLayer Name="CP Insulated Node" />

            <FeatureLayer Name="CP Rectifier/Groundbed" />

            <FeatureLayer Name="CP Test Connection" />

            <Group DisplayName="CP Circuits" IsVisible="False">

               <FeatureLayer Name="CP Circuit (Distribution Main)" IsVisible="True" />

               <FeatureLayer Name="CP Circuit (High Pressure Distribution Main)" IsVisible="True" />

               <FeatureLayer Name="CP Circuit (Transmission Main)" IsVisible="True" />

               <FeatureLayer Name="CP Circuit (Service)" IsVisible="True" />

               <FeatureLayer Name="CP Circuit (Bond Wire)" IsVisible="True" />

            </Group>

         </Group>

         <Group DisplayName="Company Geographic">

            <FeatureLayer Name="Atmospheric Corrosion Area" />

            <FeatureLayer Name="Blue Stake Boundary" />

            <FeatureLayer Name="Control Valve Area" />

            <FeatureLayer Name="District" />

            <FeatureLayer Name="GPS Line" />

            <FeatureLayer Name="GPS Point" />

            <FeatureLayer Name="Leak Survey Boundary" />

            <FeatureLayer Name="Miscellaneous Text" />

            <FeatureLayer Name="Miscellaneous Line" />

            <FeatureLayer Name="Office" />

            <FeatureLayer Name="Pipeline Classification Area" />

            <FeatureLayer Name="Public Building" />

            <FeatureLayer Name="System Map" />

         </Group>

         <Group DisplayName="Design Landbase">

            <FeatureLayer Name="Design Building" />

            <FeatureLayer Name="Design Edge of Pavement" />

            <FeatureLayer Name="Design Foreign Company Utility" />

            <FeatureLayer Name="Design Public Utility Easement" />

            <FeatureLayer Name="Design Street Centerline" />

            <FeatureLayer Name="Design Parcel" />

         </Group>

         <FeatureLayer Name="Work Location" />

         <FeatureLayer Name="Work Request" />

      </MobileMapPackageLayer>

   </Map>

   <EnableTOC>True</EnableTOC>

QueryAddin

Provides support for Identify, Find, Go to XY, Measure, Highlight/Erase, and Text tools.

The following commands are exposed to the UI:

Data Context KeyCommand
QueryAddin.QueryCommandsFindCommand
QueryAddin.QueryCommandsGoToXYCommand
QueryAddin.QueryToolsIdentifyCommand
QueryAddin.QueryToolsMeasureCommand
QueryAddin.QueryToolsHighlighterCommand
QueryAddin.QueryToolsHighlighterMenuCommand
QueryAddin.QueryToolsEraserCommand
QueryAddin.QueryToolsEraserMenuCommand
QueryAddin.QueryToolsTextCommand

The following bindable properties are also exposed:

Data Context KeyPropertyType
QueryAddin.QueryToolsIdentifyToolCheckedbool
QueryAddin.QueryToolsMeasureToolCheckedbool
QueryAddin.QueryToolsHighlighterIconImage
QueryAddin.QueryToolsHighlighterToolCheckedbool
QueryAddin.QueryToolsHighlighterTextString
QueryAddin.QueryToolsEraserIconImage
QueryAddin.QueryToolsEraserToolCheckedbool
QueryAddin.QueryToolsEraserTextString
QueryAddin.QueryToolsTextToolCheckedbool

The following views are expected to exist in the referenced view library:

The "ConfigData" section for the QueryModelExt model extension can have the following (optional) entries:

Here are some example entries:


   <Identify ResultCollection="Tree" QueryRelated="True" />

   <AttachmentDialogModel Assembly="EditAddin" ClassName="EditAttachmentDialogModel" />

LayoutAddin

Provides support for map layouts that can be printed or exported to XPS.

The following commands are exposed to the UI:

Data Context KeyCommand
LayoutAddin.LayoutModelExtOpenLayoutCommand

The following views are expected to exist in the referenced view library:

The "ConfigData" section for the LayoutModelExt model extension can have a "Layouts" entry containing one or more "Layout" entries. Each "Layout" entry must specify values for "Name", "DisplayName", "PageWidth", and "PageHeight" (using 96 dpi). A Layout may have optional "Property" entries to populate text blocks:

Here is an example XAML mark-up for a layout:


<UserControl x:Class="LayoutTest.AdHocLetterPortrait"

             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

             mc:Ignorable="d"

             d:DesignHeight="1056" d:DesignWidth="816">

   <UserControl.Resources>

      <TextBlock x:Key="Title" Text="Ad Hoc Letter Portrait" />

      <Size x:Key="PageSize" Height="1056" Width="816" />

   </UserControl.Resources>

   <Canvas Height="1056" Width="816" Background="White">

      <Border Canvas.Left="48" Canvas.Bottom="48" Width="720" Height="960" BorderBrush="Black" BorderThickness="3">

         <Grid>

            <Grid.RowDefinitions>

               <RowDefinition />

               <RowDefinition Height="48" />

            </Grid.RowDefinitions>

            <Border Grid.Row="0" Margin="12, 12, 12, 0" BorderBrush="Blue" BorderThickness="3">

               <ContentPresenter Content="{Binding MapViewContainerContent}" />

            </Border>

            <Canvas Grid.Row="1">

               <TextBlock Canvas.Bottom="12" Canvas.Left="12" FontSize="24" Text="{Binding LayoutProperties[Title], FallbackValue=Title}" />

               <TextBlock Canvas.Top="6" Canvas.Left="440" FontSize="10" Text="Scale:" />

               <TextBlock Canvas.Top="6" Canvas.Left="480" FontSize="10" Text="{Binding LayoutProperties[Scale], FallbackValue=N/A}" />

               <TextBlock Canvas.Top="24" Canvas.Left="440" FontSize="10" Text="Date:" />

               <TextBlock Canvas.Top="24" Canvas.Left="480" FontSize="10" Text="{Binding LayoutProperties[Date], FallbackValue=N/A}" />

            </Canvas>

         </Grid>

      </Border>

   </Canvas>

</UserControl>

And here is an example configuration for it:


    <Layout Name="AdHocLetterPortrait" DisplayName="Ad Hoc Letter Portrait" PageWidth="816" PageHeight="1056">

       <Properties>

          <Property Name="Title" Type="Input" Label="Map Title" />

          <Property Name="Scale" Type="Scale" PageUnit="Inch" DistanceUnit="Feet"/>

          <Property Name="Date" Type="Date" FormatString="MM-dd-yyyy" />

       </Properties>

    </Layout>

EditAddin

Provides support for online/offline editing via the Sync Framework [offline editing requires Runtime Standard licensing].

The following commands are exposed to the UI:

Data Context KeyCommand
EditAddin.EditModelExtDeleteGDBCommand
EditAddin.EditModelExtSynchronizeCommand

The following bindable properties are also exposed:

Data Context KeyPropertyType
EditAddin.EditModelExtSynchronizeVisibilityVisibility

The following views are expected to exist in the referenced view library:

In order to work with QueryAddin, the "AttachmentDialogModel" entry should be set as follows:


   <AttachmentDialogModel Assembly="EditAddin" ClassName="EditAttachmentDialogModel" />

The "ConfigData" section for the EditViewExt view extension must have the following entries:

The optional "PortalAuth" entry specifies the URL for Portal or ArcGIS Online authentication. If "AutoUserName" is "True", then the user's OS sign-in ID is automatically used.

Here is an example configuration:


   <RemoteFeatureService Url="http://myserver:6080/arcgis/rest/services/UES/Field/FeatureServer" />

   <LocalGeodatabase Path="C:\apps\FieldApp\Data\FieldEditTest.geodatabase" />

   <EditLayers GroupLayerName="Field Data" Visible="False">

      <EditLayer Name="RedPoint" />

      <EditLayer Name="RedLine" />

      <EditLayer Name="RedPoly" />

   </EditLayers>

   <AOI XMin="-116" YMin="30" XMax="-108" YMax="38" />

Here is an example of a Portal service:


   <RemoteFeatureService Url="https://gis.myserver.com/arcgis/rest/services/Gas/FieldMeter/FeatureServer" />

   <PortalAuth Url="https://gis.myserver.com/portal/sharing/rest" AutoUserName="True"/>

AppUpdateAddin

Provides support for application updates, Runtime updates, local file updates, and local dataset updates. Multiple dataset/Runtime update locations are supported. The extension makes the following assumptions:

The following commands are exposed to the UI:

Data Context KeyCommand
AppUpdateAddin.UpdateModelExtSetLocationCommand

The following bindable properties are also exposed:

Data Context KeyPropertyType
EditAddin.EditModelExtLocationVisibilityVisibility

The following views are expected to exist in the referenced view library:

The extension should be the first in the "Extensions" section of the config file. The "ConfigData" section for the UpdateModelExt model extension is optional. The following entries may or may not be present:

Here is a sample configuration:




   <SetUpdateFolder>True</SetUpdateFolder>

   <FileUpdates>

      <File Source="Packages\AZ Gas.mpk" Destination="c:\apps\FieldApp\packages" />

      <File Source="Packages\AZ Gas Black.mpk" Destination="c:\apps\FieldApp\packages" />

      <File Source="Packages\TraceGasNetwork.gpk" Destination="c:\apps\FieldApp\packages" />

      <File Source="Packages\GasTraceResults.mpk" Destination="c:\apps\FieldApp\packages" />

   </FileUpdates>

   <DatasetUpdates>

      <Dataset Name="AZLandbase.gdb" Destination="C:\apps\FieldApp\Data" />

      <Dataset Name="AZGas.gdb" Destination="C:\apps\FieldApp\Data" />

   </DatasetUpdates>



Configuration Examples for Core Extensions

Creating an Extension

More to come (hopefully)!


Return to ArcGIS Runtime page