MVVM в WPF — UserControls и GMap.NET

Я прочитал почти все учебные пособия и проверил вопросы по стеку, однако я до сих пор не знаю и не понимаю, как управлять пользовательскими элементами управления WPF в MVVM, особенно теми, которые предоставляются другими, такими как GMap.NET.

Я пытаюсь следовать шаблону MVVM в своем приложении, однако я понятия не имею, как инициализировать и управлять элементом управления GMap.NET WPF в нем. В стандартном подходе требуется такое управление:

gmap.MapProvider = GMap.NET.MapProviders.GoogleMapProvider.Instance;
GMap.NET.GMaps.Instance.Mode = GMap.NET.AccessMode.ServerOnly;
gmap.DragButton = MouseButton.Left;
gmap.SetPositionByKeywords("Paris, France");
gmap.ShowCenter = false;

Как мне это сделать без торможения MVVM? Является ли это возможным? Буду признателен за любую помощь.


person Niko    schedule 17.07.2017    source источник
comment
MVVM != нет кода программной части. Просто откройте свойства пользовательского элемента управления для всего, что нужно вашей карте, и привяжите к ним свою модель представления. Какую бы логику пользовательского интерфейса вам ни нужно было выполнить, сделайте это в коде пользовательского элемента управления.   -  person    schedule 17.07.2017
comment
@Will, так должен ли я поместить код типа gmap.DragButton = MouseButton.Left; в код позади, если он не будет затронут из виртуальной машины? Я не могу получить доступ к instanceDragButton из XAML.   -  person Niko    schedule 17.07.2017
comment
Согласен, MVVM позволяет использовать программный код, особенно при настройке поведения кнопок и т. д. во время выполнения. Модель представления — это только ваша часть данных, которая должна быть привязана к элементам в представлении. Есть ли в GMAP свойство Source или ItemSource?   -  person JWP    schedule 17.07.2017
comment
Код пользовательского интерфейса находится в вашем отделенном коде. Не вставляйте его в свои модели просмотра.   -  person    schedule 17.07.2017
comment
@JohnPeters Есть MapProvider (и этот доступен из XAML). Итак, как я понимаю, я могу сделать своего рода оболочку в отделенном коде и привязаться к этой оболочке?   -  person Niko    schedule 17.07.2017
comment
Кто-нибудь из вас будет так любезен и даст мне простой пример или ответит на вопрос? Таких, как я, ждут ответа больше.   -  person Niko    schedule 17.07.2017
comment
Почему бы вам не разместить весь код, который вы разместили в своем вопросе, в представлении? Есть ли какое-либо свойство GMap Control, которым вы должны управлять из модели представления?   -  person mm8    schedule 18.07.2017
comment
@mm8, Да, конечно. Мне нужно управлять им из ViewModel. Например, добавление и удаление маркеров, поиск по местоположению...   -  person Niko    schedule 18.07.2017


Ответы (2)


Как указано в комментариях, любой код, который просто инициализирует представление, может быть помещен в код позади.

Если возможно, свойства модели представления должны быть привязаны к представлению. Это предпочтительный способ, и он должен превзойти большинство вариантов использования.

Однако некоторые элементы управления являются сложными и имеют «расширенный» API, который состоит не только из свойств зависимостей, но также из методов и событий.

Если требуется вызвать «методы представления» из модели представления, подход, основанный на событиях, работает нормально. Поскольку представление знает модель представления, оно может подписываться на события в модели представления (например, в событии DataContextChanged). (см. также этот ответ) Пример: вы хотите вызвать метод gmap.SetPositionByKeywords из модели представления. Просто дайте модели представления событие RequestSetPositionByKeyWords, пусть представление подпишется на этот метод и вызовет gmap.SetPositionByKeywords, если событие возникло. Параметры и возвращаемые значения могут передаваться аргументами события. Это хороший подход, который соблюдает принципы MVVM.

person JanDotNet    schedule 31.07.2017
comment
Большое спасибо за ваш ответ. Попробовав несколько вариантов, все заработало! В моей виртуальной машине у меня есть: public event EventHandler<ViewEventArgs> MapSearchEvent; и private void MapSearch(string searchString) { MapSearchEvent?.Invoke(this, new ViewEventArgs(searchString)); } В моей V у меня есть: vm.MapSearchEvent += MapSearch; и мой метод: private void MapSearch(object sender, ViewModels.ViewEventArgs e) { gmap.SetPositionByKeywords(e.ParameterString); } Если это где-то тормозит MVVM, сообщите мне. - person Niko; 31.07.2017
comment
Звучит отлично. Это не ломает MVVM, потому что виртуальная машина остается независимой от представления :-). - person JanDotNet; 31.07.2017

Вы также можете создать элемент управления внутри модели представления:

GMapControl vmGmapControl{get;set;} 

в конструкторе:

vmGmapControl=new GmapControl();
//GMap control initialization logic...

и привяжите представление:

<UserControl Content="{Binding vmGmapControl}"/>

Он может не следовать MVVM, но в противном случае вам придется переписать все свойства, которые вы планируете использовать, которые в настоящее время не могут быть привязаны к свойствам зависимостей (например, к свойству Markers).

person ivelin    schedule 12.08.2020