Domanda

Poco problema con la mia applicazione Android e non so come risolverlo con MVVM Cross.

Ecco il mio modello

public class Article 
{
    string Label{ get; set; }
    string Remark { get; set; }
}
.

My ViewModel

public class ArticleViewModel: MvxViewModel
{
    public List<Article> Articles;
    ....

}
.

il mio layout.axml ...

    <LinearLayout
        android:layout_width="0dip"
        android:layout_weight="6"
        android:layout_height="fill_parent"
        android:orientation="vertical"
        android:id="@+id/layoutArticleList">
        <EditText
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:id="@+id/editSearch"
            android:text=""
            android:singleLine="True"
            android:selectAllOnFocus="true"
            android:capitalize="characters"
            android:drawableLeft="@drawable/ic_search_24"
            local:MvxBind="{'Text':{'Path':'Filter','Mode':'TwoWay'}}"
            />
      <Mvx.MvxBindableListView
            android:id="@+id/listviewArticle"
            android:choiceMode="singleChoice"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:orientation="vertical" 
            local:MvxItemTemplate="@layout/article_rowlayout"
            local:MvxBind="{'ItemsSource':{'Path':'Articles'}}" />                
    </LinearLayout>
...
.

Ed ecco il mio problema, il "articolo_rowtrayout"

...
<TableRow
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/blue">
        <TextView
            android:id="@+id/rowArticleLabel"
            android:layout_width="0dip"
            android:layout_weight="14"
            android:layout_height="wrap_content"
            android:textSize="28dip"
            local:MvxBind="{'Text':{'Path':'Label'}}" />
        <ImageButton
            android:src="@drawable/ic_modify"
            android:layout_width="0dip"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:id="@+id/rowArticleButtonModify"
            android:background="@null" 
            android:focusable="false"
            android:clickable="true"    
            local:MvxBind="{'Click':{'Path':'MyTest'}}"
          />
...
.

Il comando "Fare clic" chiamato "MyTest" è collegato all'elemento dato da MVXBindableListView.In altre parole, fai clic su Cerca un comando "MyTest" nel mio modello "Articolo", invece del mio mirino.Come posso cambiare quel comportamento per collegare il mio ViewModel "ArticleviewModel" che è responsabile della mia MVXBindableListView?

Qualche suggerimento?

È stato utile?

Soluzione

La tua analisi è decisamente corretta su dove l'evento Click sta cercando di legare.

Ci sono due approcci che generalmente prendo:

    .
  1. Usa ItemClick sull'elenco
  2. continuando a usare click ma fai un po 'di reindirizzamento sul lato viewModel.
    .

    SO ... 1

    the Menu principale nel tutorial ha un punto di vista un po 'come:

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

    Questo è usato in AXML come:

    <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"
      />
    
    .

    Questo approccio può essere fatto solo per ItemClick sull'elemento di elenco - non su singoli sottoviews all'interno dell'elenco elementi.


    .

    o ... 2

    Dal momento che non abbiamo le istruzioni di rilegatura RelativeSource in MVX, questo tipo di reindirizzamento può essere eseguito nel viewModel / codice modello.

    Questo può essere fatto presentando un wrapper abilitato al comportamento dell'oggetto modello piuttosto che l'oggetto modello stesso - ad es. Utilizzo di un List<ActiveArticle>:

    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; } } 
    }
    
    .

    L'AXML dovrebbe quindi utilizzare Bindings come:

        <TextView            ...
            local:MvxBind="{'Text':{'Path':'TheArticle.Label'}}" />
    
    .

    e

        <ImageButton
            ...
            local:MvxBind="{'Click':{'Path':'TheCommand.MyTest'}}" />
    
    .

    Un esempio di questo approccio è il campione della conferenza che utilizza withcommand

    Tuttavia ... Si prega di notare che quando si utilizza WithCommand<T> abbiamo scoperto una perdita di memoria - fondamentalmente la GarbageCollection ha rifiutato di raccogliere il MvxRelayCommand incorporato - motivo per cui WithCommand<T> è IDisposable e perché BaseSessionListViewModel Cancella l'elenco e dispiega gli elementi con i commenti sono distaccati.


    .

    Aggiornamento dopo il commento:

    Se il tuo elenco dei dati è grande - e i tuoi dati sono fissi (i tuoi articoli sono modelli senza proprietà) e non si desidera sostenere il sovraccarico di creare un grande List<WrappedArticle>, allora un modo in cui potrebbe essere quello di utilizzare una classe WrappingList<T> .

    Questo è molto simile all'approccio preso in Codice Microsoft - E.G. in elenchi di virtualizzazione in WP7 / Silverlight - http://shawnoster.com/blog/post/improving-ListBog-performance-in-silverlight-for-windows-phone-7-Data-virtualizzazione.aspx

    Per i tuoi articoli questo potrebbe essere:

    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
                };
        }
    
        #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<Wrapped> 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<DateFilter>
    
        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
    }   
    
    .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top