Your analysis is definitely correct regarding where the click event is trying to bind.
There are two approaches that I usually do:
- Use ItemClick in list
- Continued use Click, but do some redirection on the ViewModel side.
So ... 1
The main menu in the tutorial has a ViewModel a bit similar:
public class MainMenuViewModel : MvxViewModel { public List<T> Items { get; set; } public IMvxCommand ShowItemCommand { get { return new MvxRelayCommand<T>((item) => ); } } }
This is used in axml as:
<Mvx.MvxBindableListView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:local="http://schemas.android.com/apk/res/Tutorial.UI.Droid" android:layout_width="fill_parent" android:layout_height="fill_parent" local:MvxBind="{'ItemsSource':{'Path':'Items'},'ItemClick':{'Path':'ShowItemCommand'}}" local:MvxItemTemplate="@layout/listitem_viewmodel" />
This approach can only be done for ItemClick in the entire list item - not for individual subzones in list items.
Or 2
Since we don’t have any instructions for binding RelativeSource in mvx, this type of redirection can be done in ViewModel / Model code.
This can be done by presenting a wrapper with support for the Model object enabled, and not the model object itself - for example, using List<ActiveArticle> :
public ActiveArticle { Article _article; ArticleViewModel _parent; public WrappedArticle(Article article, ArticleViewModel parent) { } public IMvxCommand TheCommand { get { return MvxRelayCommand(() -> _parent.DoStuff(_article)); } } public Article TheArticle { get { return _article; } } }
Then your axml will have to use type bindings:
<TextView ... local:MvxBind="{'Text':{'Path':'TheArticle.Label'}}" />
and
<ImageButton ... local:MvxBind="{'Click':{'Path':'TheCommand.MyTest'}}" />
One example of this approach is a sample conference that uses WithCommand
However ... note that when using WithCommand<T> we found a memory leak - basically GarbageCollection refused to collect the built-in MvxRelayCommand - that is why WithCommand<T> is IDisposable and why BaseSessionListViewModel clears the list and creates WithCommand elements when views are disabled.
Update after comment:
If your data list is large - and your data is corrected (your articles are models without PropertyChanged), and you do not want to bear the overhead of creating a large List<WrappedArticle> , then one way could be to use the WrappingList<T> class.
This is very similar to the approach adopted in Microsoft code - for example, in list virtualization in WP7 / Silverlight - http://shawnoster.com/blog/post/Improving-ListBox-Performance-in-Silverlight-for-Windows-Phone-7 -Data-Virtualization.aspx
For your articles, this could be:
public class ArticleViewModel: MvxViewModel { public WrappingList<Article> Articles; // normal members... } public class Article { public string Label { get; set; } public string Remark { get; set; } } public class WrappingList<T> : IList<WrappingList<T>.Wrapped> { public class Wrapped { public IMvxCommand Command1 { get; set; } public IMvxCommand Command2 { get; set; } public IMvxCommand Command3 { get; set; } public IMvxCommand Command4 { get; set; } public T TheItem { get; set; } } private readonly List<T> _realList; private readonly Action<T>[] _realAction1; private readonly Action<T>[] _realAction2; private readonly Action<T>[] _realAction3; private readonly Action<T>[] _realAction4; public WrappingList(List<T> realList, Action<T> realAction) { _realList = realList; _realAction = realAction; } private Wrapped Wrap(T item) { return new Wrapped() { Command1 = new MvxRelayCommand(() => _realAction1(item)), Command2 = new MvxRelayCommand(() => _realAction2(item)), Command3 = new MvxRelayCommand(() => _realAction3(item)), Command4 = new MvxRelayCommand(() => _realAction4(item)), TheItem = item }; }