|
POST
|
I'm working on translate the sample to Xamarin.Forms...
... View more
06-09-2017
11:31 AM
|
0
|
5
|
6763
|
|
POST
|
I just add a MapViewViewpointChangedBehavior to handle ViewpointChanged event of the MapView and a Converter to show Envelope coordinates of the Viewpoint in DMS format.... please check here https://github.com/marceloctorres/GeonetPost.WPF
... View more
06-01-2017
01:01 PM
|
0
|
0
|
6763
|
|
POST
|
My approach is a little different I use a behavior like this: using Esri.ArcGISRuntime.Mapping;
using Esri.ArcGISRuntime.UI.Controls;
using System.Diagnostics;
using System.Windows;
using System.Windows.Interactivity;
namespace GeonetPost.WPF.Behaviors
{
public class SetMapViewViewportBehavior : Behavior<MapView>
{
/// <summary>
///
/// </summary>
public static readonly DependencyProperty ViewpointProperty =
DependencyProperty.Register(nameof(Viewpoint), typeof(Viewpoint), typeof(SetMapViewViewportBehavior));
/// <summary>
///
/// </summary>
public Viewpoint Viewpoint
{
get { return (Viewpoint)GetValue(ViewpointProperty); }
set { SetValue(ViewpointProperty, value); }
}
public SetMapViewViewportBehavior()
{
Debug.WriteLine("Hola");
}
/// <summary>
///
/// </summary>
/// <param name="e"></param>
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
if(e.Property.Name == nameof(Viewpoint))
{
SetViewpoint(this.Viewpoint);
}
}
/// <summary>
///
/// </summary>
/// <param name="vp"></param>
private async void SetViewpoint(Viewpoint vp)
{
if (vp != null)
{
var actualVp = this.AssociatedObject.GetCurrentViewpoint(ViewpointType.BoundingGeometry);
if (actualVp == null || (actualVp != null && !actualVp.Equals(vp)))
{
Debug.WriteLine("SetViewpoint");
await this.AssociatedObject.SetViewpointAsync(vp);
}
}
}
}
}
Then I add to ViewModel class: 1) a property private Viewpoint _viewpoint;
/// <summary>
///
/// </summary>
public Viewpoint Viewpoint
{
get { return _viewpoint; }
set { SetProperty(ref _viewpoint, value); }
}
2) A command: /// <summary>
///
/// </summary>
public ICommand ButtonClickCommand { get; private set; }
/// <summary>
///
/// </summary>
public ICommand ZoomCommand { get; private set; }
public MapWindowViewModel()
{
MyMap = new Map(Basemap.CreateStreets());
GraphicsOverlays = new GraphicsOverlayCollection();
ButtonClickCommand = new DelegateCommand(ButtonClickAction);
ZoomCommand = new DelegateCommand(ZoomAction);
GraphicsOverlay go = new GraphicsOverlay()
{
Id = "MyGraphicOverlay"
};
GraphicsOverlays.Add(go);
}
3) And an action: /// <summary>
///
/// </summary>
private void ZoomAction()
{
Viewpoint = new Viewpoint(4, -74, 5000000);
}
Finally, we modify the View to looks like this: <Window x:Class="GeonetPost.WPF.Views.MapWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactions"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:bh="clr-namespace:GeonetPost.WPF.Behaviors"
xmlns:esri="http://schemas.esri.com/arcgis/runtime/2013"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<esri:MapView Map="{Binding MyMap}"
GraphicsOverlays="{Binding GraphicsOverlays}">
<ei:Interaction.Behaviors>
<bh:SetMapViewViewportBehavior Viewpoint="{Binding Viewpoint}" />
</ei:Interaction.Behaviors>
</esri:MapView>
<StackPanel Grid.Row="1"
Orientation="Horizontal">
<Button Margin="5"
Width="100"
Content="Click Me!"
Background="Black"
Foreground="White"
Command="{Binding ButtonClickCommand}" />
<Button Margin="5"
Width="100"
Content="Zoom to point!"
Background="Black"
Foreground="White"
Command="{Binding ZoomCommand}" />
</StackPanel>
</Grid>
</Window>
You can find the complete code in this github site: https://github.com/marceloctorres/GeonetPost.WPF.
... View more
06-01-2017
10:08 AM
|
1
|
8
|
6763
|
|
POST
|
To implement the MVVM pattern correctly you must consider using a series of objects and interfaces so that the View (XAML code) and the class that acts as ViewModel can communicate effectively. My recommendation is to use a framework that facilitates the writing of the code. You can use Prism.Wpf from Brian Lagunas which is added to the project as a Nuget package. Here is the code for Vista: <Window x:Class="GeonetPost.WPF.Views.MapWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:esri="http://schemas.esri.com/arcgis/runtime/2013"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<esri:MapView Map="{Binding MyMap}"
GraphicsOverlays="{Binding GraphicsOverlays}">
</esri:MapView>
<Button Grid.Row="1"
Margin="5"
Width="100"
Content="Click Me!"
Background="Black"
Foreground="White"
Command="{Binding ButtonClickCommand}" />
</Grid>
</Window> You have to bind GraphicsOverlays property of the MapView to a property on your ViewModel Class. Here is the ViewModel Class; using Esri.ArcGISRuntime.Geometry;
using Esri.ArcGISRuntime.Mapping;
using Esri.ArcGISRuntime.Symbology;
using Esri.ArcGISRuntime.UI;
using Prism.Commands;
using Prism.Mvvm;
using System.Windows.Input;
using System.Windows.Media;
namespace GeonetPost.WPF.ViewModels
{
public class MapWindowViewModel : BindableBase
{
private Map _myMap;
private GraphicsOverlayCollection _grapchicsOverlays;
/// <summary>
///
/// </summary>
public Map MyMap
{
get { return _myMap; }
set { SetProperty(ref _myMap, value); }
}
/// <summary>
///
/// </summary>
public GraphicsOverlayCollection GraphicsOverlays
{
get { return _grapchicsOverlays; }
set { SetProperty(ref _grapchicsOverlays, value); }
}
/// <summary>
///
/// </summary>
public ICommand ButtonClickCommand { get; private set; }
public MapWindowViewModel()
{
MyMap = new Map(Basemap.CreateStreets());
GraphicsOverlays = new GraphicsOverlayCollection();
ButtonClickCommand = new DelegateCommand(ButtonClickAction);
GraphicsOverlay go = new GraphicsOverlay()
{
Id = "MyGraphicOverlay"
};
GraphicsOverlays.Add(go);
}
/// <summary>
///
/// </summary>
private void ButtonClickAction()
{
var g = new Graphic()
{
Geometry = new MapPoint(-74, 4, SpatialReferences.Wgs84),
Symbol = new SimpleMarkerSymbol() { Color=Colors.Green, Style= SimpleMarkerSymbolStyle.Circle, Size=10 }
};
GraphicsOverlays[0].Graphics.Add(g);
}
}
}
Another thing you have to keep in mind is the handling of events generated by the MapView such as GeoViewTapped or DrawStatusChanged that must be handled with EventTriggers or Behaviors to comply with the MVVM pattern. Marcelo.
... View more
05-31-2017
12:20 PM
|
3
|
11
|
6763
|
|
POST
|
Thanks, in fact, I am developing a cross-platform app with Xamarin.Forms (iOS, Android, UWP) and ArcGIS Runtime SDK for .NET using "shared projects".
... View more
03-01-2017
10:07 PM
|
1
|
0
|
1275
|
|
POST
|
I find the answer after drink a hot cup of coffe! The <esriUi:Mapview.Behavior> tag was bad written the right way is like that: <esriUI:MapView.Behaviors>
</esriUI:MapView.Behaviors>
... View more
03-01-2017
09:46 PM
|
2
|
0
|
1124
|
|
POST
|
I'm developing a Xamarin.Forms app with ArcGIS Runtime SDK for .NET. I don't want write code at the Code-Behind of my MapPage.xaml Form, then I wrote a Behavior to capture de ViewpointChanged event and then store the value to a property in the ViewModel class. using Esri.ArcGISRuntime.Xamarin.Forms;
using System;
using System.Windows.Input;
using Xamarin.Forms;
namespace TrabajarMapasPortal.Behaviors
{
public class MapViewViewpointChangedBehavior : BehaviorBase<MapView>
{
/// <summary>
///
/// </summary>
public static readonly BindableProperty CommandProperty = BindableProperty.Create("Command",
typeof(ICommand),
typeof(MapViewViewpointChangedBehavior));
/// <summary>
///
/// </summary>
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set
{
SetValue(CommandProperty, value);
}
}
/// <summary>
///
/// </summary>
protected override void OnAttachedTo(MapView bindable)
{
base.OnAttachedTo(bindable);
bindable.ViewpointChanged += this.MapViewViewpointChanged;
}
/// <summary>
///
/// </summary>
/// <param name="bindable"></param>
protected override void OnDetachingFrom(MapView bindable)
{
base.OnDetachingFrom(bindable);
bindable.ViewpointChanged -= this.MapViewViewpointChanged;
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MapViewViewpointChanged(object sender, EventArgs e)
{
if (this.Command != null)
{
MapView mapView = (MapView)sender;
if(mapView != null)
{
var viewpoint= mapView.GetCurrentViewpoint(Esri.ArcGISRuntime.Mapping.ViewpointType.BoundingGeometry);
if (this.Command.CanExecute(viewpoint))
{
this.Command.Execute(viewpoint);
}
}
}
}
}
}
Then I try to attach the behavior to the MapView in the xaml Form: <?xml version="1.0" encoding="utf-8" ?>
<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:local="clr-namespace:TrabajarMapasPortal.Shared;assembly=TrabajarMapasPortal"
xmlns:vm="clr-namespace:TrabajarMapasPortal.ViewModels;assembly=TrabajarMapasPortal"
xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
prism:ViewModelLocator.AutowireViewModel="True"
xmlns:bh="clr-namespace:TrabajarMapasPortal.Behaviors;assembly=TrabajarMapasPortal"
x:Class="TrabajarMapasPortal.Views.MapPage">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="70"/>
</Grid.RowDefinitions>
<esriUI:MapView x:Name="MapView"
Map="{Binding Path=Map}">
<esriUI:Mapview.Behaviors>
<bh:MapViewViewporChangedBehavior
Command="{Binding Path=UpdateViewpointCommand}" />
</esriUI:Mapview.Behaviors>
</esriUI:MapView>
<ListView x:Name="BasemapListBox"
ItemsSource="{Binding Path=BasemapChoices}"
Grid.Row="0"
IsVisible="{Binding Path=IsBasemapListVisible}">
<ListView.Behaviors>
<bh:ListViewItemTappedBehavior
Command="{Binding Path=ChangeBasemapCommand}"/>
</ListView.Behaviors>
<ListView.BackgroundColor>
<OnPlatform x:TypeArguments="Color"
Android="Black"
WinPhone="#6FFFFFFF" />
</ListView.BackgroundColor>
<ListView.Margin>
<OnPlatform x:TypeArguments="Thickness"
WinPhone="25" />
</ListView.Margin>
</ListView>
<Grid Grid.Row="1"
Margin="5,2">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button x:Name="BasemapsButton"
Grid.Column="0"
Text="Mapa Base"
Command="{Binding Path=BaseMapsCommand}" />
<Button x:Name="NewMapButton"
Grid.Column="1"
Text="Nuevo"/>
<Button x:Name="SaveMapButton"
Grid.Column="2"
Text="Guardar ..."
Command="{Binding Path=ShowSaveMapPageCommand}"/>
</Grid>
</Grid>
</ContentPage> But I get the next error message at compile time: TrabajarMapasPortal.Views.MapPage.xaml(19,10): error : Position 19:10.
Type Mapview not found in xmlns clr-namespace:Esri.ArcGISRuntime.Xamarin.Forms;
assembly=Esri.ArcGISRuntime.Xamarin.Forms
This is the ViewModel file: using System;
using System.Windows.Input;
using System.Threading.Tasks;
using Esri.ArcGISRuntime.Mapping;
using Esri.ArcGISRuntime.Portal;
using Esri.ArcGISRuntime.Security;
using Prism.Navigation;
using Prism.Events;
using Prism.Commands;
/// <summary>
///
/// </summary>
namespace TrabajarMapasPortal.ViewModels
{
using Events;
using Prism.Services;
/// <summary>
///
/// </summary>
public class MapPageViewModel : ViewModelBase
{
private Map _map;
private bool _isBasemapListVisible;
private const string ArcGISOnlineUrl = "https://www.arcgis.com/sharing/rest";
public const string AppClientId = "fqCCjw5dkUpIuZba";
private const string OAuthRedirectUrl = "https://developers.arcgis.com";
/// <summary>
///
/// </summary>
public Map Map
{
get { return this._map; }
set { SetProperty<Map>(ref this._map, value); }
}
/// <summary>
///
/// </summary>
private Viewpoint CurrentViewpoint { get; set; }
/// <summary>
///
/// </summary>
public bool IsMapSaved
{
get { return (this.Map != null && this.Map.Item != null); }
}
/// <summary>
///
/// </summary>
public string[] BasemapChoices { get; private set; }
/// <summary>
///
/// </summary>
public bool IsBasemapListVisible
{
get { return this._isBasemapListVisible; }
set { SetProperty<bool>(ref this._isBasemapListVisible, value); }
}
/// <summary>
///
/// </summary>
public ICommand BaseMapsCommand { get; private set; }
/// <summary>
///
/// </summary>
public ICommand ChangeBasemapCommand { get; private set; }
/// <summary>
///
/// </summary>
public ICommand ShowSaveMapPageCommand { get; private set; }
/// <summary>
///
/// </summary>
public ICommand UpdateViewpointCommand { get; private set; }
/// <summary>
///
/// </summary>
public MapPageViewModel(INavigationService navigationService, IEventAggregator eventAgreggator, IPageDialogService dialogService)
{
this.DialogService = dialogService;
this.EventAggregator = eventAgreggator;
this.NavigationService = navigationService;
this.EventAggregator
.GetEvent<SaveMapEvent>()
.Subscribe(SaveMapAction);
this.Map = new Map(Basemap.CreateStreetsVector());
this.BaseMapsCommand = new DelegateCommand(BaseMapsAction);
this.ChangeBasemapCommand = new DelegateCommand<string>(ChangeBasemapAction);
this.ShowSaveMapPageCommand = new DelegateCommand(this.ShowSaveMapPageAction);
this.UpdateViewpointCommand = new DelegateCommand<Viewpoint>(this.UpdateCurrentViewPointAction);
this.BasemapChoices = new string [] {
"Topográfico",
"Topográfico Vector",
"Calles",
"Calles Vector",
"Imágenes",
"Océanos"};
this.UpdateAuthenticationManager();
}
/// <summary>
///
/// </summary>
/// <param name="vp"></param>
private void UpdateCurrentViewPointAction(Viewpoint vp)
{
this.CurrentViewpoint = vp;
}
/// <summary>
///
/// </summary>
/// <param name="saveMapInfo"></param>
private async void SaveMapAction(SaveMapInfo saveMapInfo)
{
try
{
var currentViewpoint = this.Map.InitialViewpoint;
if (!this.IsMapSaved)
{
await SaveNewMapAsync(currentViewpoint, saveMapInfo.Title, saveMapInfo.Description, saveMapInfo.Tags);
await this.DialogService.DisplayAlertAsync("Mapa Guardado", "Guardado", string.Format("Se guardó {0} en AGOL", saveMapInfo.Title), "OK");
}
else
{
// TODO: update existing portal item
}
}
catch (Exception ex)
{
await this.DialogService.DisplayAlertAsync("No se pudo guardar el mapa", ex.Message, "OK");
}
}
/// <summary>
///
/// </summary>
private void BaseMapsAction()
{
this.IsBasemapListVisible = true;
}
/// <summary>
///
/// </summary>
/// <param name="basemap"></param>
private void ChangeBasemapAction(string basemap)
{
switch (basemap)
{
case "Topográfico":
this.Map.Basemap = Basemap.CreateTopographic();
break;
case "Topográfico Vector":
this.Map.Basemap = Basemap.CreateTopographicVector();
break;
case "Calles":
this.Map.Basemap = Basemap.CreateStreets();
break;
case "Calles Vector":
this.Map.Basemap = Basemap.CreateStreetsVector();
break;
case "Imágenes":
this.Map.Basemap = Basemap.CreateImagery();
break;
case "Océanos":
this.Map.Basemap = Basemap.CreateOceans();
break;
}
this.IsBasemapListVisible = false;
}
private async void ShowSaveMapPageAction()
{
await this.NavigationService.NavigateAsync("SaveMapPage");
var info = new CredentialRequestInfo
{
AuthenticationType = AuthenticationType.Token,
ServiceUri = new Uri(ArcGISOnlineUrl)
};
Credential cred = await AuthenticationManager.Current.GetCredentialAsync(info, false);
AuthenticationManager.Current.AddCredential(cred);
}
public override void OnNavigatedFrom(NavigationParameters parameters)
{
base.OnNavigatedFrom(parameters);
}
/// <summary>
///
/// </summary>
/// <param name="initialViewpoint"></param>
/// <param name="title"></param>
/// <param name="description"></param>
/// <param name="tags"></param>
/// <returns></returns>
public async Task SaveNewMapAsync(Viewpoint initialViewpoint, string title, string description, string[] tags)
{
ArcGISPortal agsOnline = await ArcGISPortal.CreateAsync(new Uri("https://www.arcgis.com/sharing/rest"));
this.Map.InitialViewpoint = initialViewpoint;
await this.Map.SaveAsAsync(agsOnline, null, title, description, tags, null);
}
/// <summary>
///
/// </summary>
/// <param name="info"></param>
/// <returns></returns>
public async Task<Credential> CreateCredentialAsync(CredentialRequestInfo info)
{
Credential credential = null;
try
{
credential = await AuthenticationManager.Current.GenerateCredentialAsync(info.ServiceUri);
}
catch (Exception ex)
{
throw (ex);
}
return credential;
}
/// <summary>
///
/// </summary>
private void UpdateAuthenticationManager()
{
ServerInfo portalServerInfo = new ServerInfo();
portalServerInfo.ServerUri = new Uri(ArcGISOnlineUrl);
portalServerInfo.TokenAuthenticationType = TokenAuthenticationType.OAuthImplicit;
OAuthClientInfo oAuthInfo = new OAuthClientInfo
{
ClientId = AppClientId,
RedirectUri = new Uri(OAuthRedirectUrl)
};
portalServerInfo.OAuthClientInfo = oAuthInfo;
AuthenticationManager thisAuthenticationManager = AuthenticationManager.Current;
thisAuthenticationManager.RegisterServer(portalServerInfo);
thisAuthenticationManager.ChallengeHandler = new ChallengeHandler(CreateCredentialAsync);
}
}
} Appreciate any help!! Marcelo.
... View more
03-01-2017
09:40 PM
|
0
|
1
|
2681
|
|
POST
|
I have to update PopupInfo from a WebMapLayer en many WebMap that uses the same FeatureLayer... How I can do this, using ArcGIS Runtime SDK?
... View more
10-12-2015
10:44 AM
|
0
|
0
|
1825
|
|
POST
|
Hello, When I try to execute the following PL-SQL code I have right results: But when I try to compile a store-procedure using a similar code I get a compilation error: What I have to do to fix this error? Marcelo...
... View more
09-20-2015
10:07 PM
|
0
|
2
|
12524
|
|
POST
|
"Shared Projects" work for Universal Apps only...(Windows Phone 8.1, Window 8.1)....
... View more
07-15-2015
12:15 PM
|
0
|
3
|
1275
|
|
POST
|
We have an issue with AttributeTable Widget...this is my code:< callbackFeaturesEstadistica: function (featureLayer) {
if (featureLayer.graphics.length > 0) {
featureLayer.name = this._consulta.name;
this.map.addLayer(featureLayer);
featureLayer.show();
featureLayer.redraw(); this.publishData({
'target': 'AttributeTable',
'layer': featureLayer
}); this.map.graphicsLayerIds.forEach(lang.hitch(this, function (layerId) { if (layerId == this._idLayerQuery) { var lyr = this.map.getLayer(layerId); this.map.removeLayer(lyr); } })) this._idLayerQuery = featureLayer.id; } else { this._divMensaje.innerText = "La consulta no arrojo datos."; this.seleccionarDiv(this._divMensaje); } }, And this is the result: Thanks for your help!
... View more
07-15-2015
10:22 AM
|
0
|
1
|
809
|
|
POST
|
But is very usefull when one have to make versions for many platforms: using Universal Apps paradigma answer the problem for Windows Store 8.1 / Windows Phone 8.1, but when the scope must be more wide?. PCL don't resolve all issues and have to rewritte a lot of code of the presentation layer, but bussiness and data layer of the App can be shared using PCL.
... View more
07-13-2015
11:06 AM
|
0
|
5
|
1275
|
|
POST
|
We have developed a WAB Widget that add a FeatureLayer to the map by code. This layer is build using a featureCollection. Later, this FeatureLayer have to be removed to add another FeatureLayer with another featureCollection as source. After the first FeatureLayer have been removed from the map the AttributeTable widget crash. Are there some special steps to do before a FeatureLayer can be removed to the map without have a negative effect to the Attribute Table? Thanks, Marcelo
... View more
07-06-2015
01:36 PM
|
0
|
3
|
3549
|
|
POST
|
There is or there will be a Portable versión of the ArcGIS Runtime SDK for .NET or for a part of it?
... View more
06-14-2015
11:27 AM
|
0
|
7
|
3775
|
|
POST
|
And don't leave out the Windows Phone version of the application. In some regions of the world, for example Latin America, smartphones with this operating system are gaining popularity, as this platform is the third most used in these regions. Sooner or later you will need to get the version for WP...
... View more
09-18-2014
10:56 AM
|
0
|
1
|
1654
|
| Title | Kudos | Posted |
|---|---|---|
| 1 | 03-25-2025 12:51 PM | |
| 1 | 06-01-2017 10:08 AM | |
| 1 | 09-28-2017 09:06 AM | |
| 1 | 07-05-2017 09:49 AM | |
| 3 | 06-12-2017 09:48 PM |
| Online Status |
Offline
|
| Date Last Visited |
2 weeks ago
|