2014-03-06 37 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