From http://stackoverflow.com/questions/13987906/cant-bind-a-mvxbindablelistview-in-twoway-mode
The way data-binding works is through an interface called
What happens in this interface is that the ViewModel sends the View a message whenever a property changes - e.g.
With a list, this doesn't help if the contents of the list itself change - e.g. when the list has an item added or removed.
To solve this, the .Net Mvvm implementation includes another interface
A collection - such as a list - can implement
For example, the collection might fire events containing hints such as:
To use this interface for a small in-memory list - e.g. less than 1000 'small' objects - all you have to do is to change your
You can see the source for the Mono ObservableCollection implementation in: https://github.com/mosa/Mono-Class-Libraries/blob/master/mcs/class/System/System.Collections.ObjectModel/ObservableCollection.cs - it is worth taking some time to look at this implementation so that you can understand a bit more about how Mvvm works with INotifyCollectionChanged.
If you use the ObservableCollection class, then your code will become:
with:
Note:
For larger collections - where you don't want all the items in memory at the same time - you may need to implement some data-store backed list yourself.
There is a brief example of one simple sqlite data-backed store in https://github.com/slodge/MvvmCross/blob/vnext/Sample%20-%20SimpleDialogBinding/SimpleDroidSql.Core/DatabaseBackedObservableCollection.cs
This virtualizing of collection data is common in WP and WPF apps - e.g. see questions and answers like Is listbox virtualized by default in WP7 Mango?
The way data-binding works is through an interface called
INotifyPropertyChanged
What happens in this interface is that the ViewModel sends the View a message whenever a property changes - e.g.
FirePropertyChanged("TestList");
With a list, this doesn't help if the contents of the list itself change - e.g. when the list has an item added or removed.
To solve this, the .Net Mvvm implementation includes another interface
INotifyCollectionChanged
. A collection - such as a list - can implement
INotifyCollectionChanged
in order to let the View know when the contents of the collection change. For example, the collection might fire events containing hints such as:
- everything has changed - NotifyCollectionChangedAction.Reset
- an item has been added - NotifyCollectionChangedAction.Add
- an item has been removed - NotifyCollectionChangedAction.Remove
- ...
To use this interface for a small in-memory list - e.g. less than 1000 'small' objects - all you have to do is to change your
List
for an ObservableCollection
- the ObservableCollection is a class from the core .Net libraries
(from Microsoft or Mono) and it will fire the correct events when you
Add/Remove list items.You can see the source for the Mono ObservableCollection implementation in: https://github.com/mosa/Mono-Class-Libraries/blob/master/mcs/class/System/System.Collections.ObjectModel/ObservableCollection.cs - it is worth taking some time to look at this implementation so that you can understand a bit more about how Mvvm works with INotifyCollectionChanged.
If you use the ObservableCollection class, then your code will become:
private ObservableCollection<MyType> _testList;
public ObservableCollection<MyType> TestList
{
get { return _testList; }
set
{
_testList = value;
FirePropertyChanged("TestList");
// in vNext use RaisePropertyChanged(() => TestList);
}
}
with:
android:layout_width="fill_parent"
android:layout_height="fill_parent"
local:MvxBind="{'ItemsSource':{'Path':'TestList'}}"
local:MvxItemTemplate="@layout/my_item_layout" />
Note:
- that the binding is
OneWay
- this means that binding is still only going from ViewModel to View - there are no updates going from View to ViewModel. - that ObservableCollection is designed to be single-threaded - so
make sure all changes to the collection are done on the UI thread - not
on a worker thread. If you need to, you can marshall work back onto the
UI thread using
InvokeOnMainThread(() => { /* do work here */ })
in a ViewModel. - that in Android, the way lists work (through the base AdapterView)
means that every time you call any update on the ObservableCollection
then the UI List will ignore the action hint (Add, Remove, etc) - it
will treat every change as a Reset and this will cause the entire list
to redraw.
For larger collections - where you don't want all the items in memory at the same time - you may need to implement some data-store backed list yourself.
There is a brief example of one simple sqlite data-backed store in https://github.com/slodge/MvvmCross/blob/vnext/Sample%20-%20SimpleDialogBinding/SimpleDroidSql.Core/DatabaseBackedObservableCollection.cs
This virtualizing of collection data is common in WP and WPF apps - e.g. see questions and answers like Is listbox virtualized by default in WP7 Mango?
No comments:
Post a Comment