| Richie's profileThe Sandpit - "We hack s...BlogLists | Help |
|
The Sandpit - "We hack so that you don't have to!"June 25 How to Surface-enable the ArcGIS API for WPFThe Applications Prototype Lab at ESRI have created a few proof-of-concepts for the Surface using the ArcGIS API for WPF. Examples of which can be seen here and here. Surface applications are essentially WPF applications running in full screen mode. When a user interacts with an application on a Surface device is not through the standard mouse API but through a specific Surface API. The code below describes how to Surface-enable the map control that comes with the ArcGIS API for WPF. This is just a basic implementation and should be treated as a developer sample rather than anything official. SurfaceMap.xamlAfter installing the Microsoft Surface SDK 1.0 (or 1.1) you will see a few extra items in the new projects dialog of Microsoft Visual Studio 2008. Select Surface Application, add a reference to the ArcGIS API for WPF assemblies and then add a new resource file called SurfaceMap.xaml. Ensure that the build action is set to page. <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:local="clr-namespace:ESRI.PrototypeLab.Surface.Ccm" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="http://schemas.microsoft.com/surface/2008" xmlns:esri="clr-namespace:ESRI.ArcGIS.Client;assembly=ESRI.ArcGIS.Client" > <Style TargetType="{x:Type local:SurfaceMap}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:SurfaceMap}"> <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" > <esri:Map Name="PART_map" PanDuration="0" ZoomDuration="0" /> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary> App.xamlNext you need to inform the compiler to load SurfaceMap.xaml as a resource. To do so, add an entry to the App.xaml file as shown below. <Application x:Class="ESRI.PrototypeLab.Surface.Ccm.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" StartupUri="SurfaceWindow1.xaml" > <Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="...generic.xaml"/> <ResourceDictionary Source="/ESRI.PrototypeLab.Surface.Ccm;component/SurfaceMap.xaml"/> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Application.Resources> </Application> SurfaceMap.csAdd a new code file called SurfaceMap.cs and make sure that the build action is set to compile. The code below contains the bulk of the logic to interpret contact (i.e. finger) manipulation. The two key points to note is the manipulation processor and the inertia processor. The manipulation processor will raise events when users manipulate performs a panning or zooming action. The inertia processor is used to continue panning if the user flicks map. using System; using System.Windows; using System.Windows.Input; using ESRI.ArcGIS.Client; using ESRI.ArcGIS.Client.Geometry; using Microsoft.Surface.Presentation; using Microsoft.Surface.Presentation.Controls; using Microsoft.Surface.Presentation.Manipulations; using Microsoft.Surface; namespace ESRI.PrototypeLab.Surface.Ccm { public partial class SurfaceMap : SurfaceUserControl { private Map m_map = null; private Affine2DManipulationProcessor m_manipulationProcessor = null; private Affine2DInertiaProcessor m_inertiaProcessorMove = null; static SurfaceMap() { FrameworkElement.DefaultStyleKeyProperty.OverrideMetadata(typeof(SurfaceMap), SurfaceWindow1.xamlThe snippet below demonstrates how to add a reference to the SurfaceMap defined in the snippets above. <s:SurfaceWindow x:Class="ESRI.PrototypeLab.Surface.Ccm.SurfaceWindow1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="http://schemas.microsoft.com/surface/2008" xmlns:local="clr-namespace:ESRI.PrototypeLab.Surface.Ccm" Title="my Title" Height="768" Width="1024" Loaded="SurfaceWindow_Loaded" > <Grid> <local:SurfaceMap x:Name="surfaceMap" /> </Grid> </s:SurfaceWindow> SurfaceWindow1.xaml.cs (code behind)In the code-behind of the Surface window, the map extent is defined and the ArcGIS Online world street map layer is added. private void SurfaceWindow_Loaded(object sender, RoutedEventArgs e) { // Add the ArcGIS Online street map ArcGISTiledMapServiceLayer streets = new ArcGISTiledMapServiceLayer() { ID = "street", Url = "http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer", Opacity = 1 }; this.surfaceMap.Map.Extent = new Envelope(-116.992383, 33.126732, -116.560400, 32.797143); this.surfaceMap.Map.Layers.Add(streets); // Listen to map events this.surfaceMap.Map.ExtentChanging += new EventHandler<ExtentEventArgs>(this.Map_ExtentChanging); this.surfaceMap.Map.ExtentChanged += new EventHandler<ExtentEventArgs>(this.Map_ExtentChanged); } This concludes this tutorial on adding Surface support to the ArcGIS API for WPF map control. For more information, please visit the ArcGIS API for Silverlight/WPF home page, support forum and resource center. Cross Country Mobility for Microsoft SurfaceYesterday the Applications Prototype Lab at ESRI released demonstration videos of two Microsoft Surface applications. The first was a demonstration of a simulated police dispatcher (announced here) and the second is a cross country mobility application discussed in this post. This Surface application is built with ESRI’s ArcGIS API for WPF and references map and geoprocessing services from ArcGIS Server. Cross country mobility is the name giving to an exercise of determining the most efficient path between two locations. Depending on the data (and parameters) the end user can find a route that is the fastest, shortest, most fuel efficient, avoids urban areas, flattest or any other condition. The first step illustrated in the video is the rating of three geographic layers: slope, vegetation and transportation. The user can assign a preference to weight one more than others. For example, slope could be a larger consideration if moving heavy equipment than the vegetation type. Secondly, items within each layer can also be rated. For example, the user can indicate that low slope is preferable to steep slopes and that grades great than 40° are “no go” (or impossible to traverse). The next step is to indicate the intended target location for the three flagged vehicles/people/units. In the demonstration video the target is represented by a bulls eye button than can dragged into position. After the three geographic layer have been rated and the target placed into position, a request is sent to ArcGIS Server to perform a weighted overlay using the user defined parameters. The result is a new geographic layer called a cost surface. A cost surface is like an image where each pixel contains a cost value, that is, the cost for an object to traverse it. The next step, uses the cost surface to find the least cost path from the three flagged objects to the target. The final step is the creation of a cost corridor. A cost corridor is an area around the least cost path with a plus or minus one, two and three percent variation. Basically, what alternative path could the three flagged objects take by sacrificing one to three percent cost (in time, money, fuel etc). This is a very brief discussion of one of many geoprocessing capabilities in the ArcGIS product suite. I would encourage you to explore this exciting technology at the ESRI website. Police Dispatcher on Microsoft SurfaceIn May 2009, the Applications Prototype Lab published a web application called “Police Dispatcher”. The application simulated a police dispatch system with real time incidents and the tracking of police vehicles. The application was built using Silverlight 2 and the ArcGIS API for Silverlight. The police dispatcher demonstration was recently ported to the Microsoft Surface as a Surface application. Surface applications are similar to standard WPF application except that they target the Surface hardware and include references to a few extra libraries. The transition was relatively trivial, for example, the application references the ArcGIS API for WPF rather than the ArcGIS API for Silverlight. In the Surface application we took advantage of some the goodness of WPF such as drop shadows and glow bitmap effects.
May 13 Adding Tab-key Support to the PropertyGrid ControlThe PropertyGrid control is convenient for adding object editing support with minimal code. However, for some reason it does not support property navigation with the tab key. Instead, clicking tab key will progressively set focus to other controls in your form. This post provides a simple subclassed PropertyGrid with support for tab-key navigation of properties.
Below is the source code to a subclassed PropertyGrid control called TabbedPropertyGrid. There were two major issues that needed to be overcome. The first is that the PropertyGrid does not raise any keyboard events, to workaround this the subclassed PropertyGrid must hijack keyboard events from the parent form. The second issue is that there is no intuitive way to navigate GridItems. However, this MSDN forum thread provided a few clues to solve this using the Griditems and Parent property. public class TabbedPropertyGrid : PropertyGrid { public TabbedPropertyGrid() : base() { } public void SetParent(Form form) { // Catch null arguments if (form == null) { throw new ArgumentNullException("form"); } // Set this property to intercept all events form.KeyPreview = true; // Listen for keydown event form.KeyDown += new KeyEventHandler(this.Form_KeyDown); } private void Form_KeyDown(object sender, KeyEventArgs e) { // Exit if cursor not in control if (!this.RectangleToScreen(this.ClientRectangle).Contains(Cursor.Position)) { return; } // Handle tab key if (e.KeyCode != Keys.Tab) { return; } e.Handled = true; e.SuppressKeyPress = true; // Get selected griditem GridItem gridItem = this.SelectedGridItem; if (gridItem == null) { return; } // Create a collection all visible child griditems in propertygrid GridItem root = gridItem; while (root.GridItemType != GridItemType.Root) { root = root.Parent; } List<GridItem> gridItems = new List<GridItem>(); this.FindItems(root, gridItems); // Get position of selected griditem in collection int index = gridItems.IndexOf(gridItem); // Select next griditem in collection this.SelectedGridItem = gridItems[++index]; } private void FindItems(GridItem item, List<GridItem> gridItems) { switch (item.GridItemType) { case GridItemType.Root: case GridItemType.Category: foreach (GridItem i in item.GridItems) { this.FindItems(i, gridItems); } break; case GridItemType.Property: gridItems.Add(item); if (item.Expanded) { foreach (GridItem i in item.GridItems) { this.FindItems(i, gridItems); } } break; case GridItemType.ArrayValue: break; } } } After adding the TabbedPropertyGrid to your form, the form must be parsed into the control using the SetParent method. public partial class Form1 : Form { public Form1() { InitializeComponent(); // Assign the form to the propertygrid this.tabbedPropertyGrid1.SetParent(this); this.tabbedPropertyGrid1.SelectedObject = this; } } Known Issues: Shift-Tab does not select properties in reverse order.
April 15 ArcGIS Server Explorer for SilverlightThe ArcGIS Server Explorer is a new contribution on the ESRI Code Gallery for dynamically generating a catalog of map services. The Silverlight control supports multiple servers. The contribution includes a sample web application that will preview map services selected in the treeview. Click here to view the live sample. The explorer control is based on the TreeView from the Silverlight 2 Toolkit. The snippet below demonstrates how to add a reference the ArcGIS Server Explorer control into a web application. The web application is listening to the page load event and the event that is raised when a user clicks on a map service. <UserControl x:Class="ServerExplorerSample.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:esri="clr-namespace:ESRI.ArcGIS;assembly=ESRI.ArcGIS" xmlns:se="clr-namespace:ESRI.ArcGIS.ServerExplorer;assembly=ESRI.ArcGIS.ServerExplorer" Loaded="UserControl_Loaded" > <Grid> <se:ServerTreeView x:Name="serverTreeView" LayerClicked="ServerTreeView_LayerClicked" /> </Grid> </UserControl> In this example, the page load event is used to add a reference to a public ArcGIS Server, namely, ArcGIS Online. You can only add a reference to local server if you are hosting the web application on your intranet. This is a Silverlight security limitation. private void UserControl_Loaded(object sender, RoutedEventArgs e) { Uri uri = new Uri("http://services.arcgisonline.com/arcgis/rest/services"); Server server = new Server(uri, "ArcGIS Online"); this.serverTreeView.Servers.Add(server); } And finally, the snippet below demonstrates how the web application is responding to the a clicked map service. The event handler contains a reference to a layer object that can be added directly to an Silverlight map control. private void ServerTreeView_LayerClicked(object sender, LayerEventArgs e) { // Add Selected Layer this.map.Layers.Clear(); e.Layer.Initialized += (evtsender, args) => { this.map.ZoomTo(e.Layer.InitialExtent); }; this.map.Layers.Add(e.Layer); } April 09 Geochat for SilverlightThe Prototype Lab at ESRI has just launched a geo-collaboration control for Silverlight. The control allows users to chat and exchange information such as graphics. Here is a live sample. Geochat is implemented in two parts.
The client/server implementation effectively allows the server to push information to the browser. This is also referred to as Comet. Source code to both of the client and server projects are provided in the download from the ESRI code gallery. Building the ServerCompiling and publishing the WCF service is straight forward. The only prerequisite is Microsoft .NET 3.5 SP1. If you are publishing the service on Microsoft Windows Vista then you may need to register the “svc” MIME type using the following command. C:\Windows\Microsoft.NET\Framework\v3.0\Windows Communication Foundation>ServiceModelReg.exe –i Building the ClientThe code gallery only includes the source code to the geochat user control rather than the entire web application. After adding a reference to the geochat assembly, the steps below will discuss how to configure it and send/receive messages. At the top of your code page add a using statement for the geochat namespace. using ESRI.ArcGIS.Chat;
In the your page (or user control) constructor use the ChatEnvironment singleton to set the name of the geochat service and begin listening to incoming messages. public Page() { InitializeComponent(); // Url to the geochat service ("service.svc" will be automatically appended) ChatEnvironment.Default.Server = "http://your.server.com/ChatService"; // Add event handler to listen for incoming messages ChatEnvironment.Default.NoteReceived += new EventHandler<NoteEventArgs>(this.ChatEnvironment_NoteReceived); } In the snippet below, geometry is converted to JSON and sent to all other Silverlight clients. if (ChatEnvironment.Default.IsConnected) { // Create data message and assign geometry DataMessage dataMessage = new DataMessage() { Text = this.GeometryToJson(new MapPoint(10,10)), Type = typeof(MapPoint).ToString() }; // Send data message to all silverlight clients ChatEnvironment.Default.SendMessage(dataMessage, null); } To send the message to an individual user rather than everyone, replace “null” with a user object. Use the following property to return a collection of all available users. ChatEnvironment.Default.Users
The snippet above referenced a method to convert ESRI’s Silverlight geometry into JSON. Since the message will be ultimately sent down the wire as a SOAP 1.1 message, the JSON string must be enclosed in a CDATA block. private string GeometryToJson(Geometry geometry) { MemoryStream memoryStream = new MemoryStream(); DataContractJsonSerializer serializer = new DataContractJsonSerializer(geometry.GetType()); serializer.WriteObject(memoryStream, geometry); memoryStream.Position = 0; StreamReader streamReader = new StreamReader(memoryStream); string json = streamReader.ReadToEnd(); memoryStream.Close(); return string.Format("CDATA[{0}]", json); } Now, let’s add code to receive incoming geometry messages. Firstly we only want to process DataMessages and ignore other messages types (eg connection, disconnection and text). The snippet below extracts the geometry from the message as well as the name of the sender. private void ChatEnvironment_NoteReceived(object sender, NoteEventArgs e) { if (e.Note.Payload.GetType() == typeof(DataMessage)) { // Get DataMessage DataMessage dataMessage = (DataMessage)e.Note.Payload; // Get Geometry Geometry geometry = this.JsonToGeometry(dataMessage.Text, dataMessage.Type); // Who sent this message? string from = e.Note.From.FriendlyName; } } Here is the code for the JsonToGeometry method referenced above. The code assumes that the incoming message is some sort of ESRI Silverlight geometry and that the JSON string is enclosed in a CDATA block. private Geometry JsonToGeometry(string json, string type) { Type t = null; if (type == typeof(MapPoint).ToString()) { t = typeof(MapPoint); } else if (type == typeof(Polyline).ToString()) { t = typeof(Polyline); } else if (type == typeof(Envelope).ToString()) { t = typeof(Envelope); } else if (type == typeof(Polygon).ToString()) { t = typeof(Polygon); } else { return null; } // JSON to Geometry string json2 = json.Substring(6, json.Length - 7); Byte[] bytes = Encoding.Unicode.GetBytes(json2); MemoryStream memoryStream = new MemoryStream(bytes); DataContractJsonSerializer dataContractJsonSerializer = new DataContractJsonSerializer(t); Geometry geometry = dataContractJsonSerializer.ReadObject(memoryStream) as Geometry; memoryStream.Close(); return geometry; } That concludes the introduction to the geochat user control for Silverlight. Enjoy! April 02 Police Dispatcher Demo – ArcGIS API for Microsoft SilverlightThis is a quick sample thrown together that demonstrates some of the capabilities of the ArcGIS API for Microsoft Silverlight. Video in Map TooltipsOne intriguing feature is the ability to extend ESRI’s map tips with multimedia content. In the police sample, video hosted by the server is streamed into the map tip. The following XAML shows how this is achieved. <esri:Map> <esri:Map.Layers> <ve:TileLayer Opacity="0" LayerStyle="AerialWithLabels"/> <ve:TileLayer Opacity="1" LayerStyle="Road"/> <esri:GraphicsLayer> <esri:GraphicsLayer.MapTip> <StackPanel Orientation="Vertical" Background="Transparent"> <TextBlock Text="..."/> <Border Width="200" Height="150" BorderBrush="SkyBlue" BorderThickness="1" HorizontalAlignment="Right" VerticalAlignment="Top" > <Border.Background> <VideoBrush SourceName="video" Stretch="UniformToFill" /> </Border.Background> </Border> </StackPanel> </esri:GraphicsLayer.MapTip> </esri:GraphicsLayer> </esri:Map.Layers> </esri:Map> Where “video” is defined as: <MediaElement x:Name="video" AutoPlay="True" Source="police-video-large.wmv" IsMuted="True" Opacity="0" IsHitTestVisible="False" MediaEnded="Video_MediaEnded" /> Animated GraphicsThe Silverlight animation environment is very powerful. This power can be leveraged by the ArcGIS API for Silverlight. For example, the incident graphics are displayed as a red icons with a rotating swirl. There are three animations in action here:
This behavior can be achieved by subclassing the ESRI MarkerSymbol and overloading the common and mouseover view states. IncidentSymbol.cs using System.IO; using System.Windows.Controls; using System.Windows.Markup; using ESRI.ArcGIS.Symbols; namespace ESRI.PrototypeLab.PoliceDispatcher { public class IncidentSymbol : MarkerSymbol { public IncidentSymbol() : base() { string key = "<your namespace>.IncidentSymbol.xaml"; Stream stream = typeof(IncidentSymbol).Assembly.GetManifestResourceStream(key); string template = new StreamReader(stream).ReadToEnd(); this.ControlTemplate = XamlReader.Load(template) as ControlTemplate; } } } IncidentSymbol.xaml <ControlTemplate xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows" > <Grid Cursor="Hand" RenderTransformOrigin="0.5,0.5" Height="50" Width="50" > <Grid.RenderTransform> <TransformGroup> <ScaleTransform x:Name="scale" ScaleX="1" ScaleY="1" /> <TranslateTransform X="-25" Y="-25"/> </TransformGroup> </Grid.RenderTransform> <vsm:VisualStateManager.VisualStateGroups> <vsm:VisualStateGroup x:Name="CommonStates"> <vsm:VisualState x:Name="Normal"> <Storyboard> <DoubleAnimation Storyboard.TargetName="rotateTransform" Storyboard.TargetProperty="Angle" From="0" To="360" Duration="0:0:3" RepeatBehavior="Forever" /> </Storyboard> </vsm:VisualState> <vsm:VisualState x:Name="MouseOver"> <Storyboard> <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetName="path" Storyboard.TargetProperty="Visibility" > <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/> </ObjectAnimationUsingKeyFrames> <DoubleAnimation BeginTime="0:0:0" Storyboard.TargetName="scale" Storyboard.TargetProperty="ScaleX" To="2" Duration="0:0:0.2" /> <DoubleAnimation BeginTime="0:0:0" Storyboard.TargetName="scale" Storyboard.TargetProperty="ScaleY" To="2" Duration="0:0:0.2" /> </Storyboard> </vsm:VisualState> </vsm:VisualStateGroup> <vsm:VisualStateGroup x:Name="SelectionStates"> <vsm:VisualState x:Name="Selected" /> <vsm:VisualState x:Name="Unselected" /> </vsm:VisualStateGroup> </vsm:VisualStateManager.VisualStateGroups> <Image HorizontalAlignment="Center" VerticalAlignment="Center" Height="32" Width="32" Source="ESRI.PrototypeLab.PoliceDispatcher;component/Images/incident.png" /> <Path x:Name="path" Opacity="1" > <Path.Data> <PathGeometry> <PathGeometry.Figures> <PathFigureCollection> <PathFigure StartPoint="25,0" IsClosed="True"> <PathFigure.Segments> <PathSegmentCollection> <ArcSegment Point="50,25" Size="25,25" SweepDirection="Clockwise" IsLargeArc="False" RotationAngle="0" /> <LineSegment Point="45,25"/> <ArcSegment Point="25,5" Size="20,20" SweepDirection="Counterclockwise" IsLargeArc="False" RotationAngle="0" /> </PathSegmentCollection> </PathFigure.Segments> </PathFigure> </PathFigureCollection> </PathGeometry.Figures> </PathGeometry> </Path.Data> <Path.Fill> <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> <GradientStop x:Name="color1" Color="#00FF0000" Offset="0"/> <GradientStop x:Name="color2" Color="#FFFF0000" Offset="1"/> </LinearGradientBrush> </Path.Fill> <Path.RenderTransform> <TransformGroup> <RotateTransform x:Name="rotateTransform" Angle="0" CenterX="25" CenterY="25" /> </TransformGroup> </Path.RenderTransform> </Path> </Grid> </ControlTemplate> April 01 Silverlight Serialization to JSONThis post will walkthrough the process of serializing and de-serializing an object to/from a JSON using Silverlight. Starting from a new Silverlight Application, add references to the System.Runtime.Serialization and System.ServiceModel.Web assemblies. At the top of the Page.xaml.cs code page, add the highlighted using statements. Still in the Page.xaml.cs code page, add a definition of a Person class that we will ultimately serialize to JSON. The class must be attributed with DataContract, a flag that denotes that the class (and all public members) are serializable. In the screenshot below, I have explicitly added DataMember attributes to shorten the property names in the JSON string.
Add a Button to the XAML and add an event handler for the click event, so that the code in Page.xaml.cs looks like the following.
Within the Button_Click method, let’s start by creating a new instance of the Person class.
Using DataContractJsonSerializer the person object can be converted to a JSON string.
Let’s add a message box to display the JSON string.
Now let’s convert the JSON string (denoted by the “json” variable) back into a Person object (denoted by “person2”).
Lastly, just to confirm that de-serialized object is correct, display the property values of “person2”.
The final step is to run this code and see if it works! Run the application in debug and click on the button you defined above to execute the serialization code. The first popup displays the serialized Person as a JSON string. The JSON is using the shorter member names defined using the DataMember attribute.
The second popup displays properties from the de-serialized person.
Presentation Extension for ArcGIS DesktopToday the ESRI Prototype Lab published a new sample entitled Presentation Extension for ArcGIS Desktop on the ArcGIS Desktop Code Gallery. This sample allows ArcMap users to give presentations directly from ArcMap without Microsoft PowerPoint. Below is a screenshot of the presentation manager, a simple-to-use window that allows the ArcMap user to create and manipulate “slides”. A slide can be consider similar to a traditional bookmark except that it also includes a title, notes, a thumbnail and most important, layer visibility. The second tab on the presentation manager defines the behavior of the presentation window. By default, the presentation window will occupy the entire extent of the primary display. When exiting a presentation you can optionally force ArcMap to display the last viewed slide and copy any ink added to the current map. To activate the presentation, click the green play button on the presentation toolbar or presentation manager window. The blue resume button will activate the presentation starting from the currently selected slide. The presentation window consists of a map, title, navigation controls and a small expander button in the lower right hand corner. Clicking the expander will display a set of somewhat familiar mapping tools. Use these buttons to interact with the map:
To exit the presentation click the “x” button or press the escape key. How was it implemented?Both the Presentation Manager and Presentation Window are built using the Windows Presentation Framework (or WPF). This is very exciting technology with virtually unlimited flexibility. The Presentation Window however is actually two WPF windows. The first is a simple window hosting the ESRI map control inside a WindowsFormsHost. A second window containing the title and buttons is overlaid on top. We used some messy Win32 calls to parent the map window to the overlay window. The dual window implementation is due to a draw order issue associated with hybrid GDI/WPF windows. Namely, it is not possible to overlay a WPF control on top of a GDI control (e.g. ESRI map control). Prerequisites
Known IssuesMicrosoft Virtual Earth layers cause the presentation window to take a long time to start. October 16 GeoTagger for ArcGIS ExplorerIn July 2008, the ESRI Prototype Lab published an extension to ArcMap that added support for MetaCarta's GeoTagger OnDemand service. This extension is now available as a custom task for ArcGIS Explorer. The task is available as a free download (including source code) from ArcScripts. Before you can use GeoTagger for ArcGIS Explorer you must create a MetaCarta account and signup to use MetaCarta web services.
The source code is available post-install. The default location of the source code is C:\Program Files\GeoTagger for ArcGIS Explorer\SOURCE. The task will be automatically be install for the current user in C:\Documents and Settings\<profile name>\Application Data\ESRI\ArcGIS Explorer\Tasks (in XP) or C:\Users\<profile name>\AppData\Roaming\ESRI\ArcGIS Explorer\Tasks (in Vista). |
||||||||||||||||
|
|