gpt4 book ai didi

xamarin - 使用 MvvmCross 如何将注释列表绑定(bind)到 MapView?

转载 作者:行者123 更新时间:2023-12-05 00:29:05 25 4
gpt4 key购买 nike

假设我有一个包含属性“注释”的 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; }
}

然后我有一个 ViewModel:
public class SiteViewModel : MvxViewModel
{

private IObservableCollection<Models.SiteItems> _siteItems;
public IObservableCollection<Models.SiteItems> SiteItems {
get{ return _siteItems; }
set{ _siteItems = value;
RaisePropertyChanged (() => SiteItems);
}
}
}

我还有一个转换器,可以将 SiteItem 转换为 MKAnnotation

所以我想我的问题是我如何绑定(bind)这样的东西,因为我们不能直接绑定(bind)到“注释”属性?我是否绑定(bind)到命令?

谢谢,任何帮助表示赞赏!

最佳答案

订阅更改集合是数据绑定(bind)的基石之一,它依赖于对 INotifyCollectionChanged 的一点了解。界面。

在 MvvmCross 源代码中,有一些示例类展示了如何订阅集合及其更改通知 - 例如MvxViewGroupExtensions.cs在 Droid 和 MvxTableViewSource.cs联系

该技术的核心是创建一个 AdapterSource监听整个列表或部分列表中的更改并采取相应措施的对象。

相同类型的方法适用于具有多个标记的 map ,尽管我们还没有任何辅助类。

在没有实际使用 Mac 或 iOS 设备的情况下,以下是我创建包装器的大致步骤......

假设我有一个 Model 对象,例如:

public class House
{
public double Lat { get; set; }
public double Lng { get; set; }
public string Name { get; set; }
}

在 ViewModel 中,例如:
public class FirstViewModel : MvxViewModel
{
public ObservableCollection<House> HouseList { get; set; }
}

完成此操作后,我们可以在 View 中为每个房屋创建一个注释类 - 例如就像是:
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; }
}

然后我们可以创建一个 HouseAnnotationManager谁负责管理 HouseList 中更改的翻译映射到 map 上显示的注释的变化。

为此,我们将提供管理器方法:
  • 创建单个注释:
    private MKAnnotation CreateAnnotation(House house)
    {
    return new HouseAnnotation(house);
    }
  • 向 map (以及本地查找表)添加注释
    private void AddAnnotationFor(House house)
    {
    var annotation = CreateAnnotation(house);
    _annotations[house] = annotation;
    _mapView.AddAnnotation(annotation);
    }
  • 从 map (和本地查找表)中删除注释
    private void RemoveAnnotationFor(House house)
    {
    var annotation = _annotations[house];
    _mapView.RemoveAnnotation(annotation);
    _annotations.Remove(house);
    }
  • 对列表执行相同的操作:
    private void AddAnnotations(IList newItems)
    {
    foreach (House house in newItems)
    {
    AddAnnotationFor(house);
    }
    }

    private void RemoveAnnotations(IList oldItems)
    {
    foreach (House house in oldItems)
    {
    RemoveAnnotationFor(house);
    }
    }
  • 回复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();
    }
    }
  • 响应整个列表更改:
    // 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);
    }
    }

  • 写完这些,你的 ViewModel 就可以拥有一个私有(private)的 _manager字段,并且可以将其创建和数据绑定(bind)为:
            _manager = new HouseAnnotationManager(myMapView);

    var set = this.CreateBindingSet<FirstView, FirstViewModel>();
    set.Bind(_manager).To(vm => vm.HouseList);
    set.Apply();

    总体而言,这可能类似于: https://gist.github.com/slodge/6070386

    免责声明:这段代码没有编译更不用说运行了,但是方法基本上是正确的(我认为)

    注:如果这对某些修复有效/无效,我非常希望它作为样本提交回 Mvx 社区;)

    同样的基本方法也应该适用于 Android - 尽管在 Android 中您还必须与设置进行斗争 - Ant、Google Play v2 和所有爵士乐。

    如果您想做进一步的 map 操作 - 例如添加房屋时更改 map 中心和缩放,那么这显然可以在您的经理中的 AddAnnotation 等方法的覆盖范围内完成。

    关于xamarin - 使用 MvvmCross 如何将注释列表绑定(bind)到 MapView?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17816684/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com