MVVMCross changing ViewModel within a MvxBindableListView

后端 未结 1 1158
被撕碎了的回忆
被撕碎了的回忆 2020-11-29 11:20

Little problem with my Android application and I don\'t know how to solve it with MVVM Cross.

Here is my Model

public class Article 
{
    string L         


        
1条回答
  •  慢半拍i
    慢半拍i (楼主)
    2020-11-29 12:03

    Your analysis is definitely correct about where the click event is trying to bind.

    There are two approaches I generally take:

    1. Use ItemClick on the List
    2. Continuing using Click but do some redirection on the ViewModel side.

    So...1

    The Main Menu in the tutorial has a ViewModel a bit like:

    public class MainMenuViewModel
        : MvxViewModel
    {
        public List Items { get; set; }
    
        public IMvxCommand ShowItemCommand
        {
            get
            {
                return new MvxRelayCommand((item) => /* do action with item */ );
            }
        }
    }
    

    This is used in axml as:

    
    

    This approach can only be done for ItemClick on the whole list item - not on individual subviews within the list items.


    Or...2

    Since we don't have any RelativeSource binding instructions in mvx, this type of redirection can be done in the ViewModel/Model code.

    This can be done by presenting a behaviour-enabled wrapper of the Model object rather than the Model object itself - e.g. using a List:

    public ActiveArticle
    {
       Article _article;
       ArticleViewModel _parent;
    
       public WrappedArticle(Article article, ArticleViewModel parent)
       {
           /* assignment */
       }
    
       public IMvxCommand TheCommand { get { return MvxRelayCommand(() -> _parent.DoStuff(_article)); } }
    
       public Article TheArticle { get { return _article; } } 
    }
    

    Your axml would then have to use bindings like:

        
    

    and

        
    

    One example of this approach is the Conference sample which uses WithCommand

    However... please note that when using WithCommand we discovered a memory leak - basically the GarbageCollection refused to collect the embedded MvxRelayCommand - which is why WithCommand is IDisposable and why BaseSessionListViewModel clears the list and disposes the WithCommand elements when views are detached.


    Update after comment:

    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 List then one way around this might be to use a WrappingList class.

    This is very similar to the approach taken in Microsoft code - e.g. in virtualizing lists in WP7/Silverlight - http://shawnoster.com/blog/post/Improving-ListBox-Performance-in-Silverlight-for-Windows-Phone-7-Data-Virtualization.aspx

    For your articles this might be:

    public class ArticleViewModel: MvxViewModel
    {
        public WrappingList
    Articles; // normal members... } public class Article { public string Label { get; set; } public string Remark { get; set; } } public class WrappingList : IList.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 _realList; private readonly Action[] _realAction1; private readonly Action[] _realAction2; private readonly Action[] _realAction3; private readonly Action[] _realAction4; public WrappingList(List realList, Action 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 }; } #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 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 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 }

    0 讨论(0)
提交回复
热议问题