Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Your analysis is definitely correct about where the click event is trying to bind.</p> <p>There are two approaches I generally take:</p> <ol> <li>Use ItemClick on the List</li> <li>Continuing using Click but do some redirection on the ViewModel side.</li> </ol> <hr> <p>So...1</p> <p>The <a href="https://github.com/slodge/MvvmCross/blob/master/Sample%20-%20Tutorial/Tutorial/Tutorial.Core/ViewModels/MainMenuViewModel.cs" rel="noreferrer">Main Menu</a> in the tutorial has a ViewModel a bit like:</p> <pre><code>public class MainMenuViewModel : MvxViewModel { public List&lt;T&gt; Items { get; set; } public IMvxCommand ShowItemCommand { get { return new MvxRelayCommand&lt;T&gt;((item) =&gt; /* do action with item */ ); } } } </code></pre> <p>This is used in axml as:</p> <pre><code>&lt;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" /&gt; </code></pre> <p>This approach can only be done for ItemClick on the whole list item - not on individual subviews within the list items.</p> <hr> <p>Or...2</p> <p>Since we don't have any <code>RelativeSource</code> binding instructions in mvx, this type of redirection can be done in the ViewModel/Model code.</p> <p>This can be done by presenting a behaviour-enabled wrapper of the Model object rather than the Model object itself - e.g. using a <code>List&lt;ActiveArticle&gt;</code>:</p> <pre><code>public ActiveArticle { Article _article; ArticleViewModel _parent; public WrappedArticle(Article article, ArticleViewModel parent) { /* assignment */ } public IMvxCommand TheCommand { get { return MvxRelayCommand(() -&gt; _parent.DoStuff(_article)); } } public Article TheArticle { get { return _article; } } } </code></pre> <p>Your axml would then have to use bindings like:</p> <pre><code> &lt;TextView ... local:MvxBind="{'Text':{'Path':'TheArticle.Label'}}" /&gt; </code></pre> <p>and</p> <pre><code> &lt;ImageButton ... local:MvxBind="{'Click':{'Path':'TheCommand.MyTest'}}" /&gt; </code></pre> <p>One example of this approach is the Conference sample which uses <a href="https://github.com/slodge/MvvmCross/blob/master/Sample%20-%20CirriousConference/Cirrious.Conference.Core/ViewModels/Helpers/WithCommand.cs" rel="noreferrer">WithCommand</a></p> <p>However... please note that when using <code>WithCommand&lt;T&gt;</code> we discovered a memory leak - basically the GarbageCollection refused to collect the embedded <code>MvxRelayCommand</code> - which is why <code>WithCommand&lt;T&gt;</code> is <code>IDisposable</code> and why <a href="https://github.com/slodge/MvvmCross/blob/master/Sample%20-%20CirriousConference/Cirrious.Conference.Core/ViewModels/SessionLists/BaseSessionListViewModel.cs" rel="noreferrer">BaseSessionListViewModel</a> clears the list and disposes the WithCommand elements when views are detached. </p> <hr> <p><strong>Update after comment:</strong></p> <p>If your data list is large - and your data is fixed (your articles are models without PropertyChanged) and you don't want to incur the overhead of creating a large <code>List&lt;WrappedArticle&gt;</code> then one way around this might be to use a <code>WrappingList&lt;T&gt;</code> class.</p> <p>This is very similar to the approach taken in Microsoft code - e.g. in virtualizing lists in WP7/Silverlight - <a href="http://shawnoster.com/blog/post/Improving-ListBox-Performance-in-Silverlight-for-Windows-Phone-7-Data-Virtualization.aspx" rel="noreferrer">http://shawnoster.com/blog/post/Improving-ListBox-Performance-in-Silverlight-for-Windows-Phone-7-Data-Virtualization.aspx</a></p> <p>For your articles this might be:</p> <pre><code>public class ArticleViewModel: MvxViewModel { public WrappingList&lt;Article&gt; Articles; // normal members... } public class Article { public string Label { get; set; } public string Remark { get; set; } } public class WrappingList&lt;T&gt; : IList&lt;WrappingList&lt;T&gt;.Wrapped&gt; { 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&lt;T&gt; _realList; private readonly Action&lt;T&gt;[] _realAction1; private readonly Action&lt;T&gt;[] _realAction2; private readonly Action&lt;T&gt;[] _realAction3; private readonly Action&lt;T&gt;[] _realAction4; public WrappingList(List&lt;T&gt; realList, Action&lt;T&gt; realAction) { _realList = realList; _realAction = realAction; } private Wrapped Wrap(T item) { return new Wrapped() { Command1 = new MvxRelayCommand(() =&gt; _realAction1(item)), Command2 = new MvxRelayCommand(() =&gt; _realAction2(item)), Command3 = new MvxRelayCommand(() =&gt; _realAction3(item)), Command4 = new MvxRelayCommand(() =&gt; _realAction4(item)), TheItem = item }; } #region Implementation of Key required methods public int Count { get { return _realList.Count; } } public Wrapped this[int index] { get { return Wrap(_realList[index]); } set { throw new NotImplementedException(); } } #endregion #region NonImplementation of other methods public IEnumerator&lt;Wrapped&gt; GetEnumerator() { throw new NotImplementedException(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public void Add(Wrapped item) { throw new NotImplementedException(); } public void Clear() { throw new NotImplementedException(); } public bool Contains(Wrapped item) { throw new NotImplementedException(); } public void CopyTo(Wrapped[] array, int arrayIndex) { throw new NotImplementedException(); } public bool Remove(Wrapped item) { throw new NotImplementedException(); } public bool IsReadOnly { get; private set; } #endregion #region Implementation of IList&lt;DateFilter&gt; public int IndexOf(Wrapped item) { throw new NotImplementedException(); } public void Insert(int index, Wrapped item) { throw new NotImplementedException(); } public void RemoveAt(int index) { throw new NotImplementedException(); } #endregion } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload