Избегайте использования async void
, за исключением обработчиков событий,
Ссылка Асинхронное / ожидание - лучшие практики асинхронного программирования
В вашем случае вы смешиваете проблемы пользовательского интерфейса, которыепринадлежат на виду.Модель представления должна предоставлять то, что необходимо представлению для выполнения его функции.
Из-за асинхронной природы используемой зависимости LocalMapService
необходимо создать обработчик асинхронных событий, чтобы управлять получением URI службы и уведомлятьпользовательский интерфейс, когда эта задача завершается через событие изменения связанного свойства.
Например,
public class ViewModel : ViewModelBase {
private readonly LocalMapService localMapService;
private readonly Model myModel;
private string serviceUri;
public ViewModel() {
myModel = new Model();
localMapService = new LocalMapService(myModel.MapPackage);
starting += onStarting;
starting(this, EventArgs.Empty);
}
private event EventHandler starting = delegate { };
private async void onStarting(object sender, EventArgs args) {
starting -= onStarting; //optional
// the following runs on background thread
await localMapService.StartAsync();
// returned to the UI thread
ServiceUri = localMapService.UrlMapService; //notifies UI
}
public string ServiceUri {
get { return serviceUri; }
set {
serviceUri = value;
OnPropertyChanged();
}
}
}
public class ViewModelBase : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged = delegate { };
protected void OnPropertyChanged([CallerMemberName] string member = "") {
PropertyChanged(this, new PropertyChangedEventArgs(member));
}
}
Таким образом, после асинхронного запуска службы пользовательский интерфейс получит уведомление об изменении.
<!-- Add a MapView Control. -->
<esriControls:MapView x:Name="MapView1">
<!-- Add a Map. -->
<esriControls:Map>
<!-- Add an ArcGISDynamicMapServiceLayer via XAML. -->
<esriLayers:ArcGISDynamicMapServiceLayer ID="mpklayer"
ServiceUri="{Bind ServiceUri}"/>
</esriControls:Map>
</esriControls:MapView>
Если цель состоит в том, чтобы иметь возможность манипулировать несколькими слоями, то я бы предложил связать свойство Map.Layers , чтобы иметь прямой доступ к коллекции слоев вмодель представления.
Модель представления может выглядеть как
public class ViewModel : ViewModelBase {
private readonly LocalMapService localMapService;
private readonly Model myModel;
private LayerCollection layers;
public ViewModel() {
myModel = new Model();
layers = new LayerCollection();
localMapService = new LocalMapService(myModel.MapPackage);
starting += onStarting;
starting(this, EventArgs.Empty);
}
private event EventHandler starting = delegate { };
private async void onStarting(object sender, EventArgs args) {
starting -= onStarting; //optional
// the following runs on background thread
await localMapService.StartAsync();
// returned to the UI thread
var serviceLayer = new ArcGISDynamicMapServiceLayer() {
ID = "mpklayer",
ServiceUri = localMapService.UrlMapService,
};
Layers.Add(serviceLayer);
}
public LayerCollection Layers {
get {
return layers;
}
}
}
И представление
<!-- Add a MapView Control. -->
<esriControls:MapView x:Name="MapView1">
<!-- Add a Map. with layers via binding-->
<esriControls:Map Layers="{Bind Layers, Mode=OneWay}" />
</esriControls:MapView>
Теперь вы можете манипулировать слоями с помощью кода по мере необходимости