Binding button click in ListView template MvvMCross
Solution 1
I've found the solution. The problem was the click binding. You should only refer to the action in the wrapper class and not both. Here are my wrapperclass & listview itemtemplate.
ItemTemplate:
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:minWidth="25px"
android:minHeight="25px">
<Button
android:layout_width="wrap_content"
android:layout_height="70dip"
android:layout_alignParentRight="true"
android:layout_marginTop="20dip"
android:layout_marginRight="20dip"
android:layout_gravity="right|center_vertical"
android:text="Bestel"
local:MvxBind="Click OrderClick" />
</LinearLayout>
WrapperClass:
public class MenuItemWrap
{
MenuItem _mnuItem;
ListPresentationViewModel _parent;
public MenuItemWrap (MenuItem item, ListPresentationViewModel parent)
{
_mnuItem = item;
_parent = parent;
}
public IMvxCommand OrderClick {
get {
return new MvxCommand (() => _parent.btnClick (_mnuItem));
}
}
public MenuItem Item{ get { return _mnuItem; } }
}
My ViewModel:
public class ListPresentationViewModel: MvxViewModel
{
private readonly ISQLService _sqlSvc;
public ListPresentationViewModel (ISQLService sqlService)
{
_sqlSvc = sqlService;
MenuCollection = WrapConverter.ConvertToWrapperClass (_sqlSvc.MenuItemGetAll(), this);
}
private int _catId;
public int CategorieId {
get{ return _catId;}
set{
_catId = value;
ChangeMenuCollection ();
}
}
private void ChangeMenuCollection()
{
MenuCollection = WrapConverter.ConvertToWrapperClass (_sqlSvc.MenuItemByCategorie (_catId), this);
}
private List<MenuItemWrap> _menuCollection = new List<MenuItemWrap> ();
public List<MenuItemWrap> MenuCollection {
get{ return _menuCollection;}
set {
_menuCollection = value;
RaisePropertyChanged (() => MenuCollection);
}
}
private IMvxCommand _orderBtnClick;
public IMvxCommand OrderBtnClick {
get {
_orderBtnClick = _orderBtnClick ?? new MvxCommand<MenuItem> (btnClick);
return _orderBtnClick;
}
}
public void btnClick (MenuItem item)
{
//Do Something
}
}
Solution 2
MvxRelayCommand
in vNext got shortened toMvxCommand
in v3 - just to save typing.- Your last problem seems to be that you are binding
Click btnClick.OrderBtnClick
- but yourMenuItemWrap
class doesn't have abtnClick
property - so you actually want to bindClick Click
?

Chris
I am a computerprogrammer, working as a developper in c# .net, Xamarin Android/iOS & Javascript for several years. Contact: [email protected]
Updated on July 26, 2022Comments
-
Chris 11 months
I have a listview with a template containing a button. When the button get's clicked i want an event to fire and return me a value of the listview row, so i can use it to add it to a database. My problem is, i don't know how to bind my buttonevent to the itemtemplate. I've tried a few approaches but with no success so far.
My Listview:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:local="http://schemas.android.com/apk/res-auto" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Mvx.MvxListView android:layout_width="fill_parent" android:layout_height="wrap_content" android:divider="#aeaeae" android:dividerHeight="1px" local:MvxBind="ItemsSource MenuCollection; ItemClick OrderBtnClick" local:MvxItemTemplate="@layout/listitem_menuitem" /> </LinearLayout>
My ItemTemplate:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:local="http://schemas.android.com/apk/res-auto" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Mvx.MvxImageView android:layout_width="100dp" android:layout_height="100dp" android:layout_margin="10dp" local:MvxBind="ImageUrl ImageUrl" /> <LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1"> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginLeft="30dp" android:textSize="40dp" local:MvxBind="Text Name" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginLeft="50dp" android:textSize="20dp" local:MvxBind="Text ShortDescription" /> </LinearLayout> <LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" android:minWidth="25px" android:minHeight="25px"> <Button android:layout_width="wrap_content" android:layout_height="70dip" android:layout_alignParentRight="true" android:layout_marginTop="20dip" android:layout_marginRight="20dip" android:layout_gravity="right|center_vertical" android:text="Bestel" android:id="@+id/button1" /> </LinearLayout> </LinearLayout>
My ViewModel:
public class ListPresentationViewModel: MvxViewModel { private readonly ISQLService _sqlSvc; public ListPresentationViewModel (ISQLService sqlService) { _sqlSvc = sqlService; MenuCollection = _sqlSvc.MenuItemGetAll (); } private List<MenuItem> _menuCollection = new List<MenuItem> (); public List<MenuItem> MenuCollection { get{ return _menuCollection;} set { _menuCollection = value; RaisePropertyChanged (() => MenuCollection); } } private IMvxCommand _orderBtnClick; public IMvxCommand OrderBtnClick{ get{ _orderBtnClick = _orderBtnClick ?? new MvxCommand(btnClick); return _orderBtnClick;} } private void btnClick() { //Do Something } }
I placed the local:MvxBind="Click OrderBtnClick" on the button in the template and on the listview. The ItemClick seems to work when i remove the button from the itemtemplate, but that's not what i'm looking for. I want the button to be triggering the event. Can anyone point me in the right direction?
UPDATE:
I've tried the second suggestion stuart lodge posted here. Here is my wrapper class:
public class MenuItemWrap { MenuItem _mnuItem; ListPresentationViewModel _parent; public MenuItemWrap () { } public MenuItemWrap (MenuItem item, ListPresentationViewModel parent) { _mnuItem = item; _parent = parent; } public IMvxCommand Click { get { return new MvxRelayCommand (() => _parent.btnClick(WrapConverter.ConvertToWrapMenuItem(_mnuItem, _parent))); } } public MenuItem Item{ get { return _mnuItem; } } }
My ViewModel:
public class ListPresentationViewModel: MvxViewModel { private readonly ISQLService _sqlSvc; public ListPresentationViewModel (ISQLService sqlService) { _sqlSvc = sqlService; MenuCollection = WrapConverter.ConvertToWrapperClass(_sqlSvc.MenuItemGetAll (), this); } private List<MenuItemWrap> _menuCollection = new List<MenuItemWrap> (); public List<MenuItemWrap> MenuCollection { get{ return _menuCollection;} set { _menuCollection = value; RaisePropertyChanged (() => MenuCollection); } } private IMvxCommand _orderBtnClick; public IMvxCommand OrderBtnClick{ get{ _orderBtnClick = _orderBtnClick ?? new MvxCommand<MenuItemWrap> (btnClick); return _orderBtnClick; } } public void btnClick(MenuItemWrap item) { MenuCollection.Clear (); } }
And here is my template:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:local="http://schemas.android.com/apk/res-auto" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Mvx.MvxImageView android:layout_width="100dp" android:layout_height="100dp" android:layout_margin="10dp" local:MvxBind="ImageUrl Item.ImageUrl" /> <LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1"> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginLeft="30dp" android:textSize="40dp" local:MvxBind="Text Item.Name" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginLeft="50dp" android:textSize="20dp" local:MvxBind="Text Item.ShortDescription" /> </LinearLayout> <LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" android:minWidth="25px" android:minHeight="25px"> <Button android:layout_width="wrap_content" android:layout_height="70dip" android:layout_alignParentRight="true" android:layout_marginTop="20dip" android:layout_marginRight="20dip" android:layout_gravity="right|center_vertical" android:text="Bestel" local:MvxBind="Click btnClick.OrderBtnClick" android:id="@+id/button1" /> </LinearLayout> </LinearLayout>
My listview works perfectly. All properties get bind correctly, and i can see the name, shortdescription and image. What does not work is the Button Click. In my application output i get an error saying: MvxBind:Warning: 76.06 Unable to bind: source property source not found Cirrious.MvvmCross.Binding.Parse.PropertyPath.PropertyTokens.MvxPropertyNamePropertyToken on MenuItemWrap
I've tried a few approaches to fix it, but with no success. I will mention i did not find the RelayCommand class in the MvvMCross assemblies so i copy pasted the code from here into my project.
-
Chris almost 10 yearsI changed my command in the MenuItemWrap class like this: public IMvxCommand OrderClick { get { return new MvxCommand (() => _parent.btnClick ()); } } And the Click command in the view like this: local:MvxBind="Click OrderClick.OrderBtnClick" But i still get the error "MvxBind:Warning: 20.65 Unable to bind: source property source not found Cirrious.MvvmCross.Binding.Parse.PropertyPath.PropertyTokens.MvxPropertyNamePropertyToken on MvxCommand". I'm a little clueless right now to what is causing this... :(
-
Nirav Shah almost 8 yearsThanks :) Nicely written.
-
AhmedW over 7 yearswhats better, this approach, or the IMvxMessenger approach mentioned here github.com/kiliman/MvxCommandToMessage
-
AhmedW over 7 yearswhat's WrapConverter.ConvertToWrapperClass ? can you share this?