假设我有一个包含属性"Annotations"的MapView.要在MapView上获取注释,您必须使用AddAnotation或AddAnotations.
public class SiteItems
{
public string Title { get; set; }
public string SubTitle { get; set; }
public string Phone { get; set; }
public string Address { get; set; }
public string Url { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
然后我有一个ViewModel:
public class SiteViewModel : MvxViewModel
{
private IObservableCollection<Models.SiteItems> _siteItems;
public IObservableCollection<Models.SiteItems> SiteItems {
get{ return _siteItems; }
set{ _siteItems = value;
RaisePropertyChanged (() => SiteItems);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我还有一个将SiteItem转换为MKAnnotation的转换器
所以我想我的问题是如何绑定这样的东西,因为我们不能直接绑定到"Annotations"属性?我绑定命令吗?
谢谢,任何帮助表示赞赏!
订阅更改集合是Data-Binding的基石之一,并且依赖于对INotifyCollectionChanged界面的一点了解.
内MvvmCross源,还有一些展示如何订阅集合及其变更通知几个示例类-如MvxViewGroupExtensions.cs在Droid和MvxTableViewSource.cs在触摸
该技术的核心是创建一个Adapter或Source对象,该对象在整个列表或列表的某些部分中监听更改,并相应地采取操作.
相同类型的方法适用于具有多个但是标记的地图 - 尽管我们还没有任何帮助类.
如果没有真正拥有Mac或iOS设备,这里大致是我创建包装器的步骤......
假设我有一个Model对象:
public class House
{
public double Lat { get; set; }
public double Lng { get; set; }
public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
在ViewModel里面,如:
public class FirstViewModel : MvxViewModel
{
public ObservableCollection<House> HouseList { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
完成后,在View中我们可以为每个House创建一个注释类 - 例如:
public class HouseAnnotation : MKAnnotation
{
public HouseAnnotation(House house)
{
// Todo - the details of actually using the house here.
// in theory you could also data-bind to the house too (e.g. if it's location were to move...)
}
public override CLLocationCoordinate2D Coordinate { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
然后,我们可以创建一个HouseAnnotationManager谁负责管理HouseList映射到地图上显示的注释中的更改的更改的转换.
要做到这一点,我们会给经理方法:
创建单个注释:
private MKAnnotation CreateAnnotation(House house)
{
return new HouseAnnotation(house);
}
Run Code Online (Sandbox Code Playgroud)向地图添加注释(以及本地查找表)
private void AddAnnotationFor(House house)
{
var annotation = CreateAnnotation(house);
_annotations[house] = annotation;
_mapView.AddAnnotation(annotation);
}
Run Code Online (Sandbox Code Playgroud)从地图中删除注释(以及从本地查找表中删除)
private void RemoveAnnotationFor(House house)
{
var annotation = _annotations[house];
_mapView.RemoveAnnotation(annotation);
_annotations.Remove(house);
}
Run Code Online (Sandbox Code Playgroud)对列表执行相同的操作:
private void AddAnnotations(IList newItems)
{
foreach (House house in newItems)
{
AddAnnotationFor(house);
}
}
private void RemoveAnnotations(IList oldItems)
{
foreach (House house in oldItems)
{
RemoveAnnotationFor(house);
}
}
Run Code Online (Sandbox Code Playgroud)回应INotifyCollection变化:
private void OnItemsSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
AddAnnotations(e.NewItems);
break;
case NotifyCollectionChangedAction.Remove:
RemoveAnnotations(e.OldItems);
break;
case NotifyCollectionChangedAction.Replace:
RemoveAnnotations(e.OldItems);
AddAnnotations(e.NewItems);
break;
case NotifyCollectionChangedAction.Move:
// not interested in this
break;
case NotifyCollectionChangedAction.Reset:
ReloadAllAnnotations();
break;
default:
throw new ArgumentOutOfRangeException();
}
}
Run Code Online (Sandbox Code Playgroud)回应整个列表更改:
// MvxSetToNullAfterBinding isn't strictly needed any more
// - but it's nice to have for when binding is torn down
[MvxSetToNullAfterBinding]
public virtual IEnumerable<House> ItemsSource
{
get { return _itemsSource; }
set { SetItemsSource(value); }
}
protected virtual void SetItemsSource(IEnumerable<House> value)
{
if (_itemsSource == value)
return;
if (_subscription != null)
{
_subscription.Dispose();
_subscription = null;
}
_itemsSource = value;
if (_itemsSource != null && !(_itemsSource is IList))
MvxBindingTrace.Trace(MvxTraceLevel.Warning,
"Binding to IEnumerable rather than IList - this can be inefficient, especially for large lists");
ReloadAllAnnotations();
var newObservable = _itemsSource as INotifyCollectionChanged;
if (newObservable != null)
{
_subscription = newObservable.WeakSubscribe(OnItemsSourceCollectionChanged);
}
}
Run Code Online (Sandbox Code Playgroud)完成所有这些后,您的ViewModel可以拥有一个私有_manager字段,并可以创建和数据绑定它:
_manager = new HouseAnnotationManager(myMapView);
var set = this.CreateBindingSet<FirstView, FirstViewModel>();
set.Bind(_manager).To(vm => vm.HouseList);
set.Apply();
Run Code Online (Sandbox Code Playgroud)
总的来说,这可能看起来像:https://gist.github.com/slodge/6070386
免责声明:此代码尚未编译,更不用说运行了,但这种方法基本上是正确的(我认为)
注意:如果这样做/不适用于某些修复,我非常希望它作为样本提交回Mvx社区;)
同样的基本方法也适用于Android - 虽然在Android中你还必须与设置 - Ant,Google Play v2和所有爵士乐进行斗争.
如果你想进行进一步的地图操作 - 例如在添加房屋时更改地图中心和缩放,那么显然可以在管理器中的方法(例如AddAnnotation)的覆盖范围内完成.
| 归档时间: |
|
| 查看次数: |
2730 次 |
| 最近记录: |