我对MVVMCross& amp; Xamarin,所以我很可能错过了一些简单的东西,但我有一个Mvx.MvxGridView布局绑定到一个简单的对象列表。
<?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线程上完成,这开始降低性能(我猜测来自连续的上下文切换?)。我最终废弃了Observable列表并实现了一个IEnumerable类,它触发了有关更改的消息并在视图中订阅了消息:
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();
});
}
}
}
答案 0 :(得分:1)
普通Mvvm和数据绑定使用INotifyPropertyChanged
这意味着,当用户界面中的网格将其ItemsSource
绑定到Bikes
上的BikeAssignmentViewModel
时,它会挂钩PropertyChanged
上的BikeAssignmentViewModel
事件< / p>
由于您从RaisePropertyChanged
开始Service
,而不是从ViewModel
开始,因此网格永远不会看到此更改通知。
解决这个问题:
RaisePropertyChange
来电
ItemsSource Service.Books
)如果您是数据绑定的新手,那么也可能值得阅读有关数据绑定的更多内容以及了解ObservableCollection和INotifyCollectionChanged的列表