private async void SyncEditsButton_Click(object sender, RoutedEventArgs e)
        {
            var gdb = await Geodatabase.OpenAsync(this.LocalDataPathTextBlock.Text);

            // create a new GeodatabaseSyncTask with the uri of the feature server to pull from
            var serverUrl           = this.featureLayerServiceUrl.Substring(0, this.featureLayerServiceUrl.LastIndexOf('/'));
            var uri                 = new Uri(serverUrl);
            var geodatabaseSyncTask = new GeodatabaseSyncTask(uri);

            var geodatabaseSyncParams = new SyncGeodatabaseParameters();

            geodatabaseSyncParams.SyncDirection = SyncDirection.Bidirectional;

            var checkStatusInterval = new TimeSpan(0, 0, 3);

            // Create a System.Progress<T> object to report status as the task executes
            var progress = new Progress <GeodatabaseStatusInfo>();

            progress.ProgressChanged += (s, info) =>
            {
                this.SyncStatusTextBlock.Text = "Sync edits: " + info.Status;
            };

            this.SyncStatusTextBlock.Text   = "Starting sync ...";
            this.SyncProgressBar.Visibility = System.Windows.Visibility.Visible;
            this.SyncStatusPanel.Visibility = System.Windows.Visibility.Visible;
            var result = await geodatabaseSyncTask.SyncGeodatabaseAsync(geodatabaseSyncParams, gdb, syncCompleteCallback, uploadCompleteCallback, checkStatusInterval, progress, new CancellationToken());
        }
Пример #2
0
        private async Task SyncGeodatabase()
        {
            // Return if not ready.
            if (_readyForEdits != EditState.Ready)
            {
                return;
            }

            // Disable the sync button.
            SyncButton.IsEnabled = false;

            // Create parameters for the sync task.
            SyncGeodatabaseParameters parameters = new SyncGeodatabaseParameters()
            {
                GeodatabaseSyncDirection = SyncDirection.Bidirectional,
                RollbackOnFailure        = false
            };

            // Get the layer ID for each feature table in the geodatabase, then add to the sync job.
            foreach (GeodatabaseFeatureTable table in _resultGdb.GeodatabaseFeatureTables)
            {
                // Get the ID for the layer.
                long id = table.ServiceLayerId;

                // Create the SyncLayerOption.
                SyncLayerOption option = new SyncLayerOption(id);

                // Add the option.
                parameters.LayerOptions.Add(option);
            }

            // Create job.
            SyncGeodatabaseJob job = _gdbSyncTask.SyncGeodatabase(parameters, _resultGdb);

            // Subscribe to progress updates.
            job.ProgressChanged += (o, e) =>
            {
                // Update the progress bar.
                UpdateProgressBar(job.Progress);
            };

            // Show the progress bar.
            GenerateSyncProgressBar.Visibility = Visibility.Visible;

            // Start the sync.
            job.Start();

            // Wait for the result.
            await job.GetResultAsync();

            // Hide the progress bar.
            GenerateSyncProgressBar.Visibility = Visibility.Collapsed;

            // Do the remainder of the work.
            HandleSyncCompleted(job);

            // Re-enable the sync button.
            SyncButton.IsEnabled = true;
        }
Пример #3
0
        // Synchronize edits in the local geodatabase with the service.
        private async void SynchronizeEdits(object sender, EventArgs e)
        {
            // Show the progress bar while the sync is working.
            _progressBar.Hidden = false;

            try
            {
                // Create a sync task with the URL of the feature service to sync.
                GeodatabaseSyncTask syncTask = await GeodatabaseSyncTask.CreateAsync(new Uri(SyncServiceUrl));

                // Create sync parameters.
                SyncGeodatabaseParameters taskParameters = await syncTask.CreateDefaultSyncGeodatabaseParametersAsync(_localGeodatabase);

                // Create a synchronize geodatabase job, pass in the parameters and the geodatabase.
                SyncGeodatabaseJob job = syncTask.SyncGeodatabase(taskParameters, _localGeodatabase);

                // Handle the JobChanged event for the job.
                job.JobChanged += (s, arg) =>
                {
                    InvokeOnMainThread(() =>
                    {
                        // Update the progress bar.
                        UpdateProgressBar(job.Progress);

                        switch (job.Status)
                        {
                        // Report changes in the job status.
                        case JobStatus.Succeeded:
                            _statusLabel.Text   = "Synchronization is complete!";
                            _progressBar.Hidden = true;
                            break;

                        case JobStatus.Failed:
                            // Report failure.
                            _statusLabel.Text   = job.Error.Message;
                            _progressBar.Hidden = true;
                            break;

                        default:
                            _statusLabel.Text = "Sync in progress ...";
                            break;
                        }
                    });
                };

                // Await the completion of the job.
                await job.GetResultAsync();
            }
            catch (Exception ex)
            {
                // Show the message if an exception occurred.
                _statusLabel.Text = "Error when synchronizing: " + ex.Message;
            }
        }
Пример #4
0
        // Synchronize edits in the local geodatabase with the service
        public async void SynchronizeEdits(object sender, EventArgs e)
        {
            // Show the progress bar while the sync is working
            _progressBar.Visibility = Android.Views.ViewStates.Visible;

            try
            {
                // Create a sync task with the URL of the feature service to sync
                GeodatabaseSyncTask syncTask = await GeodatabaseSyncTask.CreateAsync(new Uri(SyncServiceUrl));

                // Create sync parameters
                SyncGeodatabaseParameters taskParameters = await syncTask.CreateDefaultSyncGeodatabaseParametersAsync(_localGeodatabase);

                // Create a synchronize geodatabase job, pass in the parameters and the geodatabase
                SyncGeodatabaseJob job = syncTask.SyncGeodatabase(taskParameters, _localGeodatabase);

                // Handle the JobChanged event for the job
                job.JobChanged += (s, arg) =>
                {
                    RunOnUiThread(() =>
                    {
                        // Update the progress bar
                        UpdateProgressBar(job.Progress);

                        // Report changes in the job status
                        if (job.Status == JobStatus.Succeeded)
                        {
                            _messageTextBlock.Text  = "Synchronization is complete!";
                            _progressBar.Visibility = Android.Views.ViewStates.Gone;
                        }
                        else if (job.Status == JobStatus.Failed)
                        {
                            // Report failure ...
                            _messageTextBlock.Text  = job.Error.Message;
                            _progressBar.Visibility = Android.Views.ViewStates.Gone;
                        }
                        else
                        {
                            // Report that the job is in progress ...
                            _messageTextBlock.Text = "Sync in progress ...";
                        }
                    });
                };

                // Await the completion of the job
                await job.GetResultAsync();
            }
            catch (Exception ex)
            {
                // Show the message if an exception occurred
                _messageTextBlock.Text = "Error when synchronizing: " + ex.Message;
            }
        }
Пример #5
0
        private async Task SyncGeodatabase()
        {
            // Return if not ready.
            if (_readyForEdits != EditState.Ready)
            {
                return;
            }

            // Disable the sync button.
            _syncButton.Enabled = false;

            // Disable editing.
            _myMapView.GeoViewTapped -= GeoViewTapped;

            // Show the progress bar.
            _progressBar.Hidden = false;

            // Create parameters for the sync task.
            SyncGeodatabaseParameters parameters = new SyncGeodatabaseParameters
            {
                GeodatabaseSyncDirection = SyncDirection.Bidirectional,
                RollbackOnFailure        = false
            };

            // Get the layer Id for each feature table in the geodatabase, then add to the sync job.
            foreach (GeodatabaseFeatureTable table in _resultGdb.GeodatabaseFeatureTables)
            {
                // Get the ID for the layer.
                long id = table.ServiceLayerId;

                // Create the SyncLayerOption.
                SyncLayerOption option = new SyncLayerOption(id);

                // Add the option.
                parameters.LayerOptions.Add(option);
            }

            // Create job.
            _gdbSyncJob = _gdbSyncTask.SyncGeodatabase(parameters, _resultGdb);

            // Subscribe to progress updates.
            _gdbSyncJob.ProgressChanged += Job_ProgressChanged;

            // Start the sync.
            _gdbSyncJob.Start();

            // Get the result.
            await _gdbSyncJob.GetResultAsync();

            // Do the rest of the work.
            HandleSyncCompleted(_gdbSyncJob);
        }
Пример #6
0
        ////////////////////////////////////////////////////////////////
        // 同期
        ////////////////////////////////////////////////////////////////

        /**
         * サーバー(AGOL)と同期する
         * ① 同期タスクを作成する
         * ② 同期パラメータを取得する
         **/
        private async void OnSyncClick(object sender, RoutedEventArgs e)
        {
            // 同期したいレイヤーでタスクオブジェクトを作成する
            geodatabaseSyncTask = await GeodatabaseSyncTask.CreateAsync(new Uri(FEATURELAYER_SERVICE_URL));

            readGeoDatabase();

            // タスクオブジェクトから同期するためのパラメータを作成する
            syncParams = await geodatabaseSyncTask.CreateDefaultSyncGeodatabaseParametersAsync(geodatabase);

            // パラーメータを使用してgeodatabaseを同期する
            syncGeodatabase();
        }
        // Synchronize edits in the local geodatabase with the service
        public async void SynchronizeEdits(object sender, EventArgs e)
        {
            // Show the progress bar while the sync is working
            LoadingProgressBar.IsVisible = true;

            try
            {
                // Create a sync task with the URL of the feature service to sync
                GeodatabaseSyncTask syncTask = await GeodatabaseSyncTask.CreateAsync(new Uri(SyncServiceUrl));

                // Create sync parameters
                SyncGeodatabaseParameters taskParameters = await syncTask.CreateDefaultSyncGeodatabaseParametersAsync(_localGeodatabase);

                // Create a synchronize geodatabase job, pass in the parameters and the geodatabase
                SyncGeodatabaseJob job = syncTask.SyncGeodatabase(taskParameters, _localGeodatabase);

                // Handle the JobChanged event for the job
                job.JobChanged += (s, arg) =>
                {
                    // Report changes in the job status
                    if (job.Status == JobStatus.Succeeded)
                    {
                        // Report success ...
                        Device.BeginInvokeOnMainThread(() => MessageTextBlock.Text = "Synchronization is complete!");
                    }
                    else if (job.Status == JobStatus.Failed)
                    {
                        // Report failure ...
                        Device.BeginInvokeOnMainThread(() => MessageTextBlock.Text = job.Error.Message);
                    }
                    else
                    {
                        // Report that the job is in progress ...
                        Device.BeginInvokeOnMainThread(() => MessageTextBlock.Text = "Sync in progress ...");
                    }
                };

                // Await the completion of the job
                await job.GetResultAsync();
            }
            catch (Exception ex)
            {
                // Show the message if an exception occurred
                MessageTextBlock.Text = "Error when synchronizing: " + ex.Message;
            }
            finally
            {
                // Hide the progress bar when the sync job is complete
                LoadingProgressBar.IsVisible = false;
            }
        }
Пример #8
0
        private async Task SyncDataAsync(IEnumerable <Geodatabase> syncGeodatabases, SyncDirection syncDirection)
        {
            foreach (var geodatabase in syncGeodatabases)
            {
                IReadOnlyList <SyncLayerResult> results = null;
                try
                {
                    Log.Debug($"{geodatabase.Path} about to start {syncDirection} sync");

                    if (!geodatabase.HasLocalEdits() && syncDirection == SyncDirection.Upload)
                    {
                        Log.Debug("No edits skipping sync");
                        continue;
                    }

                    Log.Debug($"ServiceUrl: {geodatabase.Source}");
                    GeodatabaseSyncTask syncTask = await GeodatabaseSyncTask.CreateAsync(geodatabase.Source);

                    SyncGeodatabaseParameters syncParameters = await syncTask.CreateDefaultSyncGeodatabaseParametersAsync(geodatabase);

                    syncParameters.GeodatabaseSyncDirection = syncDirection;

                    SyncGeodatabaseJob job = syncTask.SyncGeodatabase(syncParameters, geodatabase);

                    results = await job.GetResultAsync();

                    LogResults(results);
                }
                catch (Exception e)
                {
                    Log.Error(e.Message);
                    Log.Error($"{geodatabase.Path} did not sync");
                    if (results != null)
                    {
                        LogResults(results);
                    }
                }
            }

            if (syncDirection == SyncDirection.Bidirectional || syncDirection == SyncDirection.Download)
            {
                EventAggregator.GetEvent <SyncCompleteEvent>().Publish(SyncCompleteEventArgs.Empty);
            }
        }
Пример #9
0
        private void SyncGeodatabase()
        {
            // Return if not ready
            if (_readyForEdits != EditState.Ready)
            {
                return;
            }

            // Create parameters for the sync task
            SyncGeodatabaseParameters parameters = new SyncGeodatabaseParameters()
            {
                GeodatabaseSyncDirection = SyncDirection.Bidirectional,
                RollbackOnFailure        = false
            };

            // Get the layer Id for each feature table in the geodatabase, then add to the sync job
            foreach (GeodatabaseFeatureTable table in _resultGdb.GeodatabaseFeatureTables)
            {
                // Get the ID for the layer
                long id = table.ServiceLayerId;

                // Create the SyncLayerOption
                SyncLayerOption option = new SyncLayerOption(id);

                // Add the option
                parameters.LayerOptions.Add(option);
            }

            // Create job
            SyncGeodatabaseJob job = _gdbSyncTask.SyncGeodatabase(parameters, _resultGdb);

            // Subscribe to status updates
            job.JobChanged += Job_JobChanged;

            // Subscribe to progress updates
            job.ProgressChanged += Job_ProgressChanged;

            // Start the sync
            job.Start();
        }
        private async Task SyncGeodatabaes(SyncDirection syncDirection)
        {
            foreach (var gdbPath in BidirectionalGdbs)
            {
                Geodatabase geodatabase = null;
                IReadOnlyList <SyncLayerResult> results = null;

                try
                {
                    geodatabase = await Geodatabase.OpenAsync(gdbPath);

                    Log.Debug($"{geodatabase.Path} about to start {syncDirection} sync");

                    if (!geodatabase.HasLocalEdits() && syncDirection == SyncDirection.Upload)
                    {
                        Log.Debug("No edits skipping sync");
                        continue;
                    }

                    Log.Debug($"ServiceUrl: {geodatabase.Source}");
                    GeodatabaseSyncTask syncTask = await GeodatabaseSyncTask.CreateAsync(geodatabase.Source);

                    SyncGeodatabaseParameters syncParameters = await syncTask.CreateDefaultSyncGeodatabaseParametersAsync(geodatabase);

                    syncParameters.GeodatabaseSyncDirection = syncDirection;

                    SyncGeodatabaseJob job = syncTask.SyncGeodatabase(syncParameters, geodatabase);

                    results = await job.GetResultAsync();

                    LogResults(results);
                }
                catch (Exception e)
                {
                    Log.Error(e.Message);
                    Log.Error($"{geodatabase?.Path} did not sync");
                    LogResults(results);
                }
            }
        }
Пример #11
0
        private void SyncGeodatabase()
        {
            // Return if not ready
            if (_readyForEdits != EditState.Ready)
            {
                return;
            }

            // 同期タスクのパラメータを作成する
            SyncGeodatabaseParameters parameters = new SyncGeodatabaseParameters()
            {
                GeodatabaseSyncDirection = SyncDirection.Bidirectional,
                RollbackOnFailure        = false
            };

            // ジオデータベース内の各フィーチャテーブルのレイヤー ID を取得してから、同期ジョブに追加する
            foreach (GeodatabaseFeatureTable table in _resultGdb.GeodatabaseFeatureTables)
            {
                // レイヤーのIDを取得する
                long id = table.ServiceLayerId;

                // CSyncLayerOption を作成する
                SyncLayerOption option = new SyncLayerOption(id);

                // オプションを追加する
                parameters.LayerOptions.Add(option);
            }

            // ジョブを作成する
            SyncGeodatabaseJob job = _gdbSyncTask.SyncGeodatabase(parameters, _resultGdb);

            // ステータス更新
            job.JobChanged += Job_JobChanged;

            // プログレスバーの更新
            job.ProgressChanged += Job_ProgressChanged;

            // 同期を開始する
            job.Start();
        }
Пример #12
0
        public static async Task <Geodatabase> DownloadOrUpdateFeatureService(String serviceUrl, Extent extent, Action <double, double> ProgressUpdate)
        {
            var task     = new TaskCompletionSource <Geodatabase>();
            var syncTask = await GeodatabaseSyncTask.CreateAsync(new Uri(serviceUrl));

            var         serviceName         = PullArcgisServiceName(serviceUrl);
            var         geodatabaseFilePath = Path.Combine(CachePath, serviceName + ".gdb");
            Geodatabase ret;

            if (File.Exists(geodatabaseFilePath))
            {
                //add service to existing mobile geodatabase
                ret = await Geodatabase.OpenAsync(geodatabaseFilePath);

                // create sync parameters
                var taskParameters = new SyncGeodatabaseParameters()
                {
                    RollbackOnFailure        = true,
                    GeodatabaseSyncDirection = SyncDirection.Download
                };

                // create a synchronize geodatabase job, pass in the parameters and the geodatabase
                SyncGeodatabaseJob syncGdbJob = syncTask.SyncGeodatabase(taskParameters, ret);

                syncGdbJob.JobChanged += (async(object sender, EventArgs e) =>
                {
                    var job = sender as SyncGeodatabaseJob;
                    switch (job?.Status)
                    {
                    case JobStatus.Succeeded:
                        await syncTask.UnregisterGeodatabaseAsync(ret);

                        task.SetResult(ret);
                        break;

                    case JobStatus.Failed:
                        if (job.Error != null)
                        {
                            task.SetException(job.Error);
                        }
                        else
                        {
                            String message = string.Empty;

                            var m = from msg in job.Messages select msg.Message;
                            message += ": " + string.Join <string>("\n", m);
                            task.SetException(new Exception(message));
                        }
                        task.SetResult(null);
                        break;
                    }
                });

                syncGdbJob.ProgressChanged += ((object sender, EventArgs e) =>
                {
                    ProgressUpdate?.Invoke(syncGdbJob.Progress, 1.0);
                });

                // Start the job
                var result = await syncGdbJob.GetResultAsync();
            }
            else
            {
                var envelope = new Envelope(extent.MinX, extent.MinY, extent.MaxX, extent.MaxY, SpatialReference.Create(extent.WKID));
                // Get the default parameters for the generate geodatabase task
                GenerateGeodatabaseParameters generateParams = await syncTask.CreateDefaultGenerateGeodatabaseParametersAsync(envelope);

                // Create a generate geodatabase job
                var generateGdbJob = syncTask.GenerateGeodatabase(generateParams, geodatabaseFilePath);

                // Handle the job changed event
                generateGdbJob.JobChanged += (async(object sender, EventArgs e) =>
                {
                    var job = sender as GenerateGeodatabaseJob;
                    switch (job?.Status)
                    {
                    case JobStatus.Succeeded:
                        ret = await job.GetResultAsync();

                        await syncTask.UnregisterGeodatabaseAsync(ret);

                        task.SetResult(ret);
                        break;

                    case JobStatus.Failed:
                        if (job.Error != null)
                        {
                            task.SetException(job.Error);
                        }
                        else
                        {
                            String message = string.Empty;

                            var m = from msg in job.Messages select msg.Message;
                            message += ": " + string.Join <string>("\n", m);
                            task.SetException(new Exception(message));
                        }
                        task.SetResult(null);
                        break;
                    }
                });

                // Handle the progress changed event (to show progress bar)
                generateGdbJob.ProgressChanged += ((object sender, EventArgs e) =>
                {
                    ProgressUpdate?.Invoke(generateGdbJob.Progress, 1.0);
                });

                // Start the job
                generateGdbJob.Start();
            }
            return(await task.Task);
        }
Пример #13
0
        public async Task<GeodatabaseStatusInfo> SyncGeodatabase(string url, Geodatabase gdb, bool unregister, bool syncing)
        {
            Console.WriteLine("Starting Sync " + DateTime.Now + " --> " + syncing);
            var syncTask = new GeodatabaseSyncTask(new Uri(url));


            var layerIdsAndName = new Dictionary<int, string>();

            FeatureServiceInfo serviceInfo = await syncTask.GetServiceInfoAsync();
            foreach (LayerServiceInfo layerServiceInfo in serviceInfo.Layers)
            {
                if (!layerIdsAndName.ContainsKey(layerServiceInfo.ID))
                {
                    layerIdsAndName.Add(layerServiceInfo.ID, layerServiceInfo.Name);
                }
            }


            


            var tcs = new TaskCompletionSource<GeodatabaseStatusInfo>();
            Action<GeodatabaseStatusInfo, Exception> completionAction = (info, ex) =>
            {
                if (ex != null)
                {
                    tcs.SetException(ex);
                    return;
                }
                tcs.SetResult(info);
            };

            var syncProgress = new Progress<GeodatabaseStatusInfo>();
            syncProgress.ProgressChanged += (sndr, sts) => Console.WriteLine("Status:" + sts.Status.ToString() + "," +" --> " + syncing + "," + sts.SubmissionTime + "," + sts.ResultUri);


            IDictionary<int, LayerSyncInfo> layerSync = null;

            layerSync = new Dictionary<int, LayerSyncInfo>();
            foreach (var id_name in layerIdsAndName)
            {
                    var layerQuery = new LayerSyncInfo { SyncDirection = SyncDirection.Bidirectional };
                    layerSync.Add(id_name.Key, layerQuery);
                
            }
            Action<UploadResult> uploadAction = result => { Console.Write(""); };

            //should we remove sync direction since it should be defined in layers?
            var syncParams = new SyncGeodatabaseParameters(gdb) { RollbackOnFailure = false, UnregisterGeodatabase = unregister, LayerSyncInfos = layerSync, SyncDirection = SyncDirection.Bidirectional };
            Console.WriteLine("Calling sync " + DateTime.Now);
            await syncTask.SyncGeodatabaseAsync(syncParams, gdb,
                completionAction,
                uploadAction,
                TimeSpan.FromSeconds(3),
                syncProgress,
                CancellationToken.None);
            
            

            return await tcs.Task;

            

        }
		// function to submit a sync task 
		// -the url for the feature service and the path to the local geodatabase are passed in
		public async Task SyncronizeEditsAsync(FeatureLayerInfo featureLayerInfo, Uri uri)
		{
			// create sync parameters
			var taskParameters = new SyncGeodatabaseParameters
			{
				RollbackOnFailure = true,
				SyncDirection = SyncDirection.Bidirectional
			};

			// cancel if an earlier call was made and hasn't completed
			if (_syncCancellationTokenSource != null)
			{
				_syncCancellationTokenSource.Cancel();
			}

			// create a new cancellation token
			_syncCancellationTokenSource = new CancellationTokenSource();
			var cancelToken = _syncCancellationTokenSource.Token;


			// create a sync task with the url of the feature service to sync
			var syncTask = new GeodatabaseSyncTask(uri);

			// create a new Progress object to report updates to the sync status
			var progress = new Progress<GeodatabaseStatusInfo>();
			progress.ProgressChanged += (sender, s) => { _model.SetMessageInfo("Progress: " + s.Status.ToString()); };

			// call SyncGeodatabaseAsync and pass in: sync params, local geodatabase, completion callback, update interval, progress, and cancellation token

			var geodatabaseFeatureTable = featureLayerInfo.FeatureLayer.FeatureTable as GeodatabaseFeatureTable;

			var gdbResult = await syncTask.SyncGeodatabaseAsync(
				taskParameters,
				geodatabaseFeatureTable.Geodatabase,
				(p, q) =>
				{
					// reset the cancellation token source
					_syncCancellationTokenSource = null;

					// if unsuccessful, report the exception and return
					if (q != null)
					{
						_model.SetMessageInfo("An exception occured: " + q.Message);
						return;
					}

					// if successful, notify the user
					_model.SetMessageInfo("--- Sync completed ---");

					//// optionally, do something with the result
					//var resultUri = p.ResultUri;
					// ...

					UpdateToc(featureLayerInfo);
					_model.SetSyncState(CheckSyncState(false));
				},
				null,
				new TimeSpan(0, 0, 10),
				progress,
				cancelToken);
		}
Пример #15
0
        private async void Sync_Click(object sender, RoutedEventArgs e)
        {
            var tcs = new TaskCompletionSource <GeodatabaseStatusInfo>();
            Action <GeodatabaseStatusInfo, Exception> completionAction = (info, ex) =>
            {
                if (ex != null)
                {
                    tcs.SetException(ex);
                }
                tcs.SetResult(info);
            };

            Geodatabase gdb      = null;
            var         syncTask = new GeodatabaseSyncTask(new Uri(uristring));

            try
            {
                gdb = await Esri.ArcGISRuntime.Data.Geodatabase.OpenAsync(@"C:\Temp\10_2_7Demo\WildlifeLocal.geodatabase");

                var table = gdb.FeatureTables.FirstOrDefault();

                var lyr = new FeatureLayer
                {
                    ID           = table.Name,
                    DisplayName  = table.Name,
                    FeatureTable = table
                };

                MyMapView.Map.Layers.Add(lyr);

                Console.WriteLine(table.Name);
            }
            catch (Exception et)
            {
                Console.WriteLine(et.Message);
            }

            var taskParameters = new SyncGeodatabaseParameters()
            {
                RollbackOnFailure = false,
                SyncDirection     = Esri.ArcGISRuntime.Tasks.Offline.SyncDirection.Bidirectional
            };

            // cancel if an earlier call was made and hasn't completed
            if (_syncCancellationTokenSource != null)
            {
                _syncCancellationTokenSource.Cancel();
            }

            // create a new cancellation token
            _syncCancellationTokenSource = new CancellationTokenSource();
            var cancelToken = _syncCancellationTokenSource.Token;

            // create a new Progress object to report updates to the sync status
            var progress = new Progress <GeodatabaseStatusInfo>();

            progress.ProgressChanged += (sender2, s) =>
            {
                Console.WriteLine(s.Status);
            };

            try
            {
                // call SyncGeodatabaseAsync and pass in: sync params, local geodatabase, completion callback, update interval, progress, and cancellation token
                var gdbResult = await syncTask.SyncGeodatabaseAsync(
                    taskParameters,
                    gdb,
                    this.syncCompleteCallback,
                    null,
                    new TimeSpan(0, 0, 2),
                    progress,
                    cancelToken);
            }
            catch (ArcGISWebException a)
            {
                Console.WriteLine(a.Code);
                Console.WriteLine(a.StackTrace);
            }
        }