2014-03-06 34 views
0

我很新MVVMCross & Xamarin,所以很可能我错过了简单的东西,但我有一个Mvx.MvxGridView布局绑定到一个简单的对象列表。MVVMCross(Droid)GridView不会无焦点更新?

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:local="http://schemas.android.com/apk/res-auto" 
    android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent"> 
    <Mvx.MvxGridView 
     android:numColumns="5" 
     android:verticalSpacing="15dp" 
     android:horizontalSpacing="15dp" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     local:MvxBind="ItemsSource Bikes" 
     local:MvxItemTemplate="@layout/bikeassignmentview_bikeelement" /> 
</LinearLayout> 

的观点很简单:

namespace Keiser.MPM.Screen.Droid.Views 
{ 
    using Android.App; 

    [Activity(Theme = "@style/Theme.FullScreen")] 
    public class BikeAssignmentView : BaseView 
    { 
     protected override void OnCreate(Android.OS.Bundle bundle) 
     { 
      base.OnCreate(bundle); 
      this.SetContentView(Resource.Layout.BikeAssignmentView_Page); 
     } 
    } 
} 

同样的,视图模型:

namespace Keiser.MPM.Screen.Core.ViewModels 
{ 
    using System.Collections.Generic; 
    using System.Windows.Input; 
    using Cirrious.CrossCore; 
    using Cirrious.MvvmCross.ViewModels; 
    using Keiser.MPM.Screen.Core.Models.Bikes; 

    public class BikeAssignmentViewModel : BaseViewModel 
    { 
     private IBikeManagerService _bikeManagerService; 
     private List<Bike> _bikes; 
     public List<Bike> Bikes { get { return _bikes; } } 

     public BikeAssignmentViewModel(IBikeManagerService bikeManagerService) 
     { 
      _bikeManagerService = bikeManagerService; 
      _bikes = _bikeManagerService.Bikes; 
     } 
    } 
} 

在自行车名单实际上是始发服务嵌套一路下跌的服务等级:

namespace Keiser.MPM.Screen.Core.Models.Bikes 
{ 
    using System; 
    using System.Linq; 
    using System.Threading; 
    using System.Collections.Generic; 
    using Cirrious.CrossCore; 
    using Cirrious.CrossCore.Core; 
    using Cirrious.MvvmCross.ViewModels; 
    using Cirrious.MvvmCross.Plugins.Messenger; 
    using Core.Models.Settings; 

    public class BikeManagerService : MvxNotifyPropertyChanged, IBikeManagerService 
    { 
     public object BikesLocker = new object(); 
     private List<Bike> _bikes = new List<Bike>(); 
     public List<Bike> Bikes 
     { 
      get { return _bikes; } 
      set { _bikes = value; RaisePropertyChanged(() => Bikes); } 
     } 

     // --- Other boring code... 
    } 
} 

这是问题。如果视图加载时列表为空,网格视图将不会动态填充。如果我输入带有填充列表的页面,它将正确加载,并且将为添加到列表中的新对象添加网格,但是它不会从列表中移除已放置的网格,直到我单击屏幕上的一点。对象继续正确更新,直到对象被丢弃。然后对象的域停止工作,但它们不会消失。此外,如果列表回到空白,视图将不会再次更新。

我错过了什么吗?我应该使视图无效吗?任何帮助或资源将不胜感激!

[=======================解决方案==================== ===]

最终的解决办法是将列表转换为可观察集合: 接口:

namespace Keiser.MPM.Screen.Core.Models.Helpers 
{ 
    using System.Collections.Generic; 
    using System.Collections.Specialized; 
    using System.ComponentModel; 

    public interface IObservableCollection<T> 
     : IList<T> 
      , INotifyPropertyChanged 
      , INotifyCollectionChanged 
    { 
    } 
} 

类:

namespace Keiser.MPM.Screen.Core.Models.Helpers 
{ 
    using System.Collections.Generic; 
    using System.Collections.ObjectModel; 

    public class SimpleObservableCollection<T> 
     : ObservableCollection<T> 
     , IObservableCollection<T> 
    { 
     public SimpleObservableCollection(List<T> source) : base(source) { } 

     protected override void OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 
     { 
      base.OnCollectionChanged(e); 
     } 
    } 
} 

到收集的所有更改必须是在主UI线程上完成,哪个开始降低性能(我从连续的上下文切换中猜测)?我结束了再杀可观察的名单和实施一个IEnumerable类火灾的变化的消息,订阅消息中的观点:使用INotifyPropertyChanged

这意味着

namespace Keiser.MPM.Screen.Droid.Views 
{ 
    using Android.App; 
    using Android.Widget; 
    using Cirrious.MvvmCross.Plugins.Messenger; 

    [Activity(Theme = "@style/Theme.FullScreen")] 
    public class BikeAssignmentView : BaseView 
    { 
     protected MvxSubscriptionToken _BikeListToken; 

     protected override void OnCreate(Android.OS.Bundle bundle) 
     { 
      base.OnCreate(bundle); 
      this.SetContentView(Resource.Layout.BikeAssignmentView_Page); 
      var gridView = FindViewById<GridView>(Resource.Id.gridview); 

      _BikeListToken = Cirrious.CrossCore.Mvx.Resolve<IMvxMessenger>().SubscribeOnMainThread<Core.Models.Bikes.BikesChangedMessage>(message => 
      { 
       ((BaseAdapter)gridView.Adapter).NotifyDataSetChanged(); 
      }); 
     } 
    } 
} 

回答

1

普通MVVM和数据绑定作品当用户界面中的网格结合其ItemsSourceBikesBikeAssignmentViewModel然后将其挂接到上BikeAssignmentViewModel

PropertyChanged事件既然你是从你射击而不是从你的ViewModel,那么网格永远不会看到这个改变通知。

要解决此问题:

  • 你能找到一种方法,以提高从视图模型的RaisePropertyChange调用,而不是服务
  • 你会发现到网格的服务绑定,而还有一种方式至于ViewModel(例如结合ItemsSource Service.Books

如果你是新来的数据绑定那么它也可能是值得阅读了更多有关数据绑定和列表还了解的ObservableCollection和INotifyCollectionChanged

+0

我最终找到您的帖子几个月后又遇到类似的情况,发现它需要在主UI线程上实现ObservableCollections和执行列表更改。这些共同解决了这个问题。 – BayssMekanique

+0

如果您一次更新整个列表,则不需要obscollection - 仅在增量更改时才需要。 – Stuart