Click or drag to resize

KmlDatasetRootNodes Property

Gets this dataset's root KML nodes as a KmlNodeCollection.

Namespace:  Esri.ArcGISRuntime.Ogc
Assembly:  Esri.ArcGISRuntime (in Esri.ArcGISRuntime.dll) Version: 100.7.0.0
Syntax
C#
public KmlNodeCollection RootNodes { get; }

Property Value

Type: KmlNodeCollection
Remarks

Used to traverse the KmlNode objects for examining/using individual KML features. RootNodes is populated after a KML dataset has finished loading successfully.

It should be noted that a typical KML document will have multiple levels of nested KML nodes. To traverse through all of the KML node information in a KmlDataset, it is recommended to recursively test all KmlNodes to see if they contain additional child KmlNodes. When writing your recursive function pay particular attention to the properties: KmlDataset.RootNodes, KmlNetworkLink.ChildNodes, and KmlContainer.ChildNodes (inherited by KmlDocument and KmlFolder).

Examples

Android

Example Name: PlayKmlTours

Play tours in KML files.

Code example screen shot.

C#
// Copyright 2019 Esri.
// 
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific 
// language governing permissions and limitations under the License.

using Android.App;
using Android.OS;
using Android.Views;
using Android.Widget;
using ArcGISRuntime.Samples.Managers;
using Esri.ArcGISRuntime.Mapping;
using Esri.ArcGISRuntime.Ogc;
using Esri.ArcGISRuntime.UI.Controls;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using Debug = System.Diagnostics.Debug;

namespace ArcGISRuntimeXamarin.Samples.PlayKmlTours
{
    [Activity (ConfigurationChanges=Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.ScreenSize)]
    [ArcGISRuntime.Samples.Shared.Attributes.Sample(
        "Play a KML tour",
        "Layers",
        "Play tours in KML files.",
        "")]
    [ArcGISRuntime.Samples.Shared.Attributes.OfflineData("f10b1d37fdd645c9bc9b189fb546307c")]
    public class PlayKmlTours : Activity
    {
        // Hold references to the UI controls.
        private SceneView _mySceneView;
        private Button _playButton;
        private Button _pauseButton;
        private Button _resetButton;

        // The KML tour controller provides player controls for KML tours.
        private readonly KmlTourController _tourController = new KmlTourController();

        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);

            Title = "Play a KML tour";

            CreateLayout();
            Initialize();
        }

        private async void Initialize()
        {
            // Load the scene with a basemap and a terrain surface.
            _mySceneView.Scene = new Scene(Basemap.CreateImagery());
            _mySceneView.Scene.BaseSurface.ElevationSources.Add(new ArcGISTiledElevationSource(new Uri("https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer")));

            // Get the URL to the data.
            string filePath = DataManager.GetDataFolder("f10b1d37fdd645c9bc9b189fb546307c", "Esri_tour.kmz");
            Uri kmlUrl = new Uri(filePath);

            // Create the KML dataset and layer.
            KmlDataset dataset = new KmlDataset(kmlUrl);
            KmlLayer layer = new KmlLayer(dataset);

            // Add the layer to the map.
            _mySceneView.Scene.OperationalLayers.Add(layer);

            try
            {
                // Load the dataset.
                await dataset.LoadAsync();

                // Find the first KML tour.
                FindKmlTour(dataset.RootNodes);

                // Handle absence of tour gracefully.
                if (_tourController.Tour == null)
                {
                    throw new InvalidOperationException("No tour found. Can't enable touring for a KML file with no tours.");
                }

                // Listen for changes to the tour status.
                _tourController.Tour.PropertyChanged += Tour_PropertyChanged;

                // Enable the play button.
                _playButton.Enabled = true;
            }
            catch (Exception e)
            {
                Debug.WriteLine(e.ToString());
                new AlertDialog.Builder(this).SetMessage(e.ToString()).SetTitle("Error").Show();
            }
        }

        private void FindKmlTour(IEnumerable<KmlNode> rootNodes)
        {
            // Hold a list of nodes to explore.
            Queue<KmlNode> nodesToExplore = new Queue<KmlNode>();

            // Add each root node to the list.
            foreach (KmlNode rootNode in rootNodes)
            {
                nodesToExplore.Enqueue(rootNode);
            }

            // Keep exploring until a tour is found or there are no more nodes.
            while (nodesToExplore.Any())
            {
                // Remove a node from the queue.
                KmlNode currentNode = nodesToExplore.Dequeue();

                // If the node is a tour, use it.
                if (currentNode is KmlTour tourNode)
                {
                    _tourController.Tour = tourNode;
                    return;
                }

                // If the node is a container, add all of its children to the list of nodes to explore.
                if (currentNode is KmlContainer container)
                {
                    foreach (KmlNode node in container.ChildNodes)
                    {
                        nodesToExplore.Enqueue(node);
                    }
                }

                // Otherwise, continue.
            }
        }

        private void Tour_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            // Skip for everything except tour status property changes.
            if (e.PropertyName != nameof(KmlTour.TourStatus))
            {
                return;
            }

            // Set the UI based on the current state of the tour.
            switch (_tourController.Tour.TourStatus)
            {
                case KmlTourStatus.Completed:
                case KmlTourStatus.Initialized:
                    _playButton.Enabled = true;
                    _pauseButton.Enabled = false;
                    break;
                case KmlTourStatus.Paused:
                    _playButton.Enabled = true;
                    _pauseButton.Enabled = false;
                    _resetButton.Enabled = true;
                    break;
                case KmlTourStatus.Playing:
                    _resetButton.Enabled = true;
                    _playButton.Enabled = false;
                    _pauseButton.Enabled = true;
                    break;
            }
        }

        // Play the tour when the button is pressed.
        private void Play_Clicked(object sender, EventArgs e) => _tourController?.Play();

        // Pause the tour when the button is pressed.
        private void Pause_Clicked(object sender, EventArgs e) => _tourController?.Pause();

        // Reset the tour when the button is pressed.
        private void Reset_Clicked(object sender, EventArgs e) => _tourController?.Reset();

        protected override void OnStop()
        {
            base.OnStop();

            // Reset the tour controller when the sample closes - avoids a crash.
            _tourController?.Pause();
            _tourController?.Reset();
        }

        private void CreateLayout()
        {
            // Create a new vertical layout for the app.
            var layout = new LinearLayout(this) {Orientation = Orientation.Vertical};

            // Add a help label.
            TextView helpLabel = new TextView(this);
            helpLabel.Text = "Use the buttons to play the tour. Contains audio. 🎧";
            layout.AddView(helpLabel);

            // Add a row with buttons.
            _playButton = new Button(this) {Text = "Play", Enabled = false};
            _playButton.Click += Play_Clicked;
            _pauseButton = new Button(this) {Text = "Pause", Enabled = false};
            _pauseButton.Click += Pause_Clicked;
            _resetButton = new Button(this) {Text = "Reset", Enabled = false};
            _resetButton.Click += Reset_Clicked;

            LinearLayout rowLayout = new LinearLayout(this) {Orientation = Orientation.Horizontal};

            LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(
                ViewGroup.LayoutParams.MatchParent,
                ViewGroup.LayoutParams.MatchParent,
                1.0f
            );
            _playButton.LayoutParameters = param;
            _pauseButton.LayoutParameters = param;
            _resetButton.LayoutParameters = param;

            rowLayout.AddView(_playButton);
            rowLayout.AddView(_pauseButton);
            rowLayout.AddView(_resetButton);

            layout.AddView(rowLayout);

            // Add the scene view to the layout.
            _mySceneView = new SceneView(this);
            layout.AddView(_mySceneView);

            // Show the layout in the app.
            SetContentView(layout);
        }
    }
}
Examples

Xamarin Forms Android

Example Name: PlayKmlTours

Play tours in KML files.

Code example screen shot.

C#
// Copyright 2019 Esri.
// 
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific 
// language governing permissions and limitations under the License.

using ArcGISRuntime.Samples.Managers;
using Esri.ArcGISRuntime.Mapping;
using Esri.ArcGISRuntime.Ogc;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using Xamarin.Forms;

namespace ArcGISRuntimeXamarin.Samples.PlayKmlTours
{
    [ArcGISRuntime.Samples.Shared.Attributes.Sample(
        "Play a KML tour",
        "Layers",
        "Play tours in KML files.",
        "")]
    [ArcGISRuntime.Samples.Shared.Attributes.OfflineData("f10b1d37fdd645c9bc9b189fb546307c")]
    public partial class PlayKmlTours : ContentPage, IDisposable
    {
        // The KML tour controller provides player controls for KML tours.
        private readonly KmlTourController _tourController = new KmlTourController();

        public PlayKmlTours()
        {
            InitializeComponent();
            Initialize();
        }

        private async void Initialize()
        {
            // Load the scene with a basemap and a terrain surface.
            MySceneView.Scene = new Scene(Basemap.CreateImagery());
            MySceneView.Scene.BaseSurface.ElevationSources.Add(new ArcGISTiledElevationSource(new Uri("https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer")));

            // Get the URL to the data.
            string filePath = DataManager.GetDataFolder("f10b1d37fdd645c9bc9b189fb546307c", "Esri_tour.kmz");
            Uri kmlUrl = new Uri(filePath);

            // Create the KML dataset and layer.
            KmlDataset dataset = new KmlDataset(kmlUrl);
            KmlLayer layer = new KmlLayer(dataset);

            // Add the layer to the map.
            MySceneView.Scene.OperationalLayers.Add(layer);

            try
            {
                // Load the dataset.
                await dataset.LoadAsync();

                // Find the first KML tour.
                FindKmlTour(dataset.RootNodes);

                // Handle absence of tour gracefully.
                if (_tourController.Tour == null)
                {
                    throw new InvalidOperationException("No tour found. Can't enable touring for a KML file with no tours.");
                }

                // Listen for changes to the tour status.
                _tourController.Tour.PropertyChanged += Tour_PropertyChanged;

                // Enable the play button.
                PlayButton.IsEnabled = true;

                // Hide the status bar.
                LoadingStatusBar.IsVisible = false;
            }
            catch (Exception e)
            {
                Debug.WriteLine(e.ToString());
                await Application.Current.MainPage.DisplayAlert("Error", e.ToString(), "OK");
            }
        }

        private void FindKmlTour(IEnumerable<KmlNode> rootNodes)
        {
            // Hold a list of nodes to explore.
            Queue<KmlNode> nodesToExplore = new Queue<KmlNode>();

            // Add each root node to the list.
            foreach (KmlNode rootNode in rootNodes)
            {
                nodesToExplore.Enqueue(rootNode);
            }

            // Keep exploring until a tour is found or there are no more nodes.
            while (nodesToExplore.Any())
            {
                // Remove a node from the queue.
                KmlNode currentNode = nodesToExplore.Dequeue();

                // If the node is a tour, use it.
                if (currentNode is KmlTour tour)
                {
                    _tourController.Tour = tour;
                    return;
                }

                // If the node is a container, add all of its children to the list of nodes to explore.
                if (currentNode is KmlContainer container)
                {
                    foreach (KmlNode node in container.ChildNodes)
                    {
                        nodesToExplore.Enqueue(node);
                    }
                }

                // Otherwise, continue.
            }
        }

        private void Tour_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            // Skip for everything except tour status property changes.
            if (e.PropertyName != nameof(KmlTour.TourStatus))
            {
                return;
            }

            // Set the UI based on the current state of the tour.
            switch (_tourController.Tour.TourStatus)
            {
                case KmlTourStatus.Completed:
                case KmlTourStatus.Initialized:
                    PlayButton.IsEnabled = true;
                    PauseButton.IsEnabled = false;
                    break;
                case KmlTourStatus.Paused:
                    PlayButton.IsEnabled = true;
                    PauseButton.IsEnabled = false;
                    ResetButton.IsEnabled = true;
                    break;
                case KmlTourStatus.Playing:
                    ResetButton.IsEnabled = true;
                    PlayButton.IsEnabled = false;
                    PauseButton.IsEnabled = true;
                    break;
            }
        }

        // Play the tour when the button is pressed.
        private void Play_Clicked(object sender, EventArgs e) => _tourController?.Play();

        // Pause the tour when the button is pressed.
        private void Pause_Clicked(object sender, EventArgs e) => _tourController?.Pause();

        // Reset the tour when the button is pressed.
        private void Reset_Clicked(object sender, EventArgs e) => _tourController?.Reset();

        public void Dispose()
        {
            // Reset the tour when the user leaves the sample.
            _tourController?.Pause();
            _tourController?.Reset();
        }
    }
}
XAML
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"             
             xmlns:esriUI="clr-namespace:Esri.ArcGISRuntime.Xamarin.Forms;assembly=Esri.ArcGISRuntime.Xamarin.Forms"
             xmlns:resources="clr-namespace:Forms.Resources;assembly=ArcGISRuntime"
             x:Class="ArcGISRuntimeXamarin.Samples.PlayKmlTours.PlayKmlTours">
    <RelativeLayout>
        <esriUI:SceneView x:Name="MySceneView" Style="{StaticResource SceneWithFormStyle}"
                        BindingContext="{x:Reference Name=ResponsiveFormContainer}" />
        <resources:ResponsiveFormContainer x:Name="ResponsiveFormContainer">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
                <Label Text="Use the buttons to control the tour. Contains audio. 🎧"
                           Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3"
                           Margin="0,0,0,5"
                           />
                <Button x:Name="PlayButton"
                        Grid.Row="1" Grid.Column="0"
                        Text="Play"
                        IsEnabled="False"
                        Clicked="Play_Clicked" />
                <Button x:Name="PauseButton"
                        Grid.Row="1" Grid.Column="1"
                        Margin="5,0,5,0"
                        Text="Pause"
                        IsEnabled="False"
                        Clicked="Pause_Clicked" />
                <Button x:Name="ResetButton"
                        Grid.Row="1" Grid.Column="2"
                        Text="Reset"
                        IsEnabled="False"
                        Clicked="Reset_Clicked" />
                <ActivityIndicator x:Name="LoadingStatusBar"
                                   Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="3"
                                   Margin="0,5,0,0"
                                   IsEnabled="True" IsRunning="True"  />
            </Grid>
        </resources:ResponsiveFormContainer>
    </RelativeLayout>
</ContentPage>
See Also
Additional Examples
Hyperlink to ExampleDescription
ListKmlContentsList the contents of a KML file. KML files can contain a hierarchy of features, including network links to other KML content.
PlayKmlToursPlay tours in KML files.