Binding button click in ListView template MvvMCross

10,282

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

  1. MvxRelayCommand in vNext got shortened to MvxCommand in v3 - just to save typing.
  2. Your last problem seems to be that you are binding Click btnClick.OrderBtnClick - but your MenuItemWrap class doesn't have a btnClick property - so you actually want to bind Click Click ?
Share:
10,282
Chris
Author by

Chris

I am a computerprogrammer, working as a developper in c# .net, Xamarin Android/iOS &amp; Javascript for several years. Contact: [email protected]

Updated on July 26, 2022

Comments

  • Chris
    Chris over 1 year

    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
    Chris over 10 years
    I 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‌​.MvxPropertyNameProp‌​ertyToken on MvxCommand". I'm a little clueless right now to what is causing this... :(
  • Nirav Shah
    Nirav Shah almost 9 years
    Thanks :) Nicely written.
  • AhmedW
    AhmedW about 8 years
    whats better, this approach, or the IMvxMessenger approach mentioned here github.com/kiliman/MvxCommandToMessage
  • AhmedW
    AhmedW about 8 years
    what's WrapConverter.ConvertToWrapperClass ? can you share this?