Title

Saturday, 7 February 2015

MVVMCross - Button inside ListItem


I have created a List with a Model class called User. The List Item contains a button, and I would like to trigger a command on the viewmodel containing the list, instead of the button. Is it possible to set ItemsSource to an ObservableCollection, but set the DataContext of the List to the ViewModel containing the ObservableCollection.

I have a ViewModel which contains an ObservaleCollection:

FindFriendsViewModel:

 private ObservableCollection<User> _SearchResult = new ObservableCollection<User>();     public ObservableCollection<User> SearchResult   {   get   {   return _SearchResult;   }   set   {   _SearchResult = value;   }   }  

And a View which shows the List, FindFriendsView:

 <LinearLayout   android:orientation="vertical"   android:layout_width="match_parent"   android:layout_height="wrap_content"   android:background="@drawable/LoginActivity_LoginFormContainer"   android:layout_marginTop="10dip">   <MvxListView   android:id="@+id/FindFriendsView_SearchResult"   android:layout_width="fill_parent"   android:layout_height="fill_parent"   android:orientation="vertical"   android:fastScrollEnabled="true"   android:background="@color/transparent"   android:cacheColorHint="@color/transparent"   local:MvxItemTemplate="@layout/listitem_user"   local:MvxBind="ItemsSource SearchResult" />   </LinearLayout>  

The ListItem:

<LinearLayout   android:layout_width="wrap_content"   android:layout_height="wrap_content"   android:layout_toRightOf="@id/imageview"   android:layout_marginLeft="10dp"   android:orientation="vertical"   android:layout_centerVertical="true">   <LinearLayout   android:layout_width="wrap_content"   android:layout_height="wrap_content">   <TextView   android:layout_width="wrap_content"   android:layout_height="wrap_content"   android:singleLine="true"   android:textSize="18dp"   local:MvxBind="Text FirstName"   android:layout_gravity="center" />   <TextView   android:layout_width="wrap_content"   android:layout_height="wrap_content"   android:layout_marginLeft="2dp"   android:singleLine="true"   android:textSize="18dp"   local:MvxBind="Text LastName"   android:layout_gravity="center" />   </LinearLayout>   <TextView   android:layout_width="wrap_content"   android:layout_height="wrap_content"   android:singleLine="true"   android:textSize="16dp"   android:textColor="@color/darkgrey"   local:MvxBind="Text Email" />  </LinearLayout>  <LinearLayout   android:layout_width="wrap_content"   android:layout_height="wrap_content"   android:layout_alignParentRight="true"   android:padding="5dp">   <Button   android:id="@+id/ListItemUser_BtnFollow"   android:layout_width="wrap_content"   android:layout_height="wrap_content"   style="@style/GreyButton"   android:drawableLeft="@drawable/ic_action_user_red"   android:textColor="@color/black"   android:textSize="13dp"   android:text="@string/listitem_user_follow"   local:MvxBind="Click FollowCommand; Visibility IsFriend, Converter=Visibility"/>   <Button   android:id="@+id/ListItemUser_BtnFollowing"   android:layout_width="wrap_content"   android:layout_height="wrap_content"   style="@style/RedButton"   android:drawableLeft="@drawable/ic_action_tick"   android:textSize="13dp"   android:clickable="false"   android:text="@string/listitem_user_following"   local:MvxBind="Visibility IsFriend, Converter=InvertedVisibility"/>  </LinearLayout>  

The ListItem contains two buttons, where only one of them is visible at a time, and only one of them contains a Click Command. I would love to be able to get the Button to trigger a command on the FindFriendsViewModel, instead of the Model Class User.

Answer

You can utilize weak references (or WeakSubscribe as it's implemented in MvvmCross) to implement the functionality that you want. In your view model, you can subscribe to INotifyPropertyChanged of your models that you bind to the list. Once you get a notification that a button fired an ICommand, your ViewModel can respond accordingly.

Here's a little example

using Cirrious.CrossCore.WeakSubscription;    foreach (var sale in Sales)  {   var token = sale.WeakSubscribe(sale_PropertyChanged);  }    void sale_PropertyChanged(object sender, PropertyChangedEventArgs e)  {   if (e.PropertyName == "Accepted")   {   CalculateSalesTotals();   }  }  
Answer2

Better try to use swipelistview. I will do it, hopefully it will be possible to wrap this lib. Currently i solved my problem (button inside listitem) with longpresss <-> context menu.

Answer3

Whenever you need to fire commands from a listitem, you will need to use a viewmodel wrapper around your listitem class. The wrapper will implement the command, and then axml will then bind to the command in the wrapper. If you want the command to execute in the list viewmodel, then you can pass an action to the wrapper, and execute the action in the viewmodel.

No comments:

Post a Comment