Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
245 views
in Technique[技术] by (71.8m points)

android - Bind button click inside customlayout using mvvmcross and mvxlistview

i wanted to bind a button click event inside my customlayout, below is my customlayout

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="63dp">
    <LinearLayout
        android:orientation="horizontal"
        android:minWidth="25px"
        android:minHeight="25px"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
        <Button
            android:text="Accept"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/acceptBtnOnList"
            android:background="@color/green_color"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:textStyle="bold"
            android:layout_weight="1"
            android:textColor="@android:color/background_light"
            local:MvxBind="Click AcceptCommand" />
    </LinearLayout>
</RelativeLayout>

below is my ListView layout

<?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="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@android:color/background_light">
    <Mvx.MvxListView
        android:id="@+id/ListView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:cacheColorHint="#FFDAFF7F"
        local:MvxBind="ItemsSource MyList; ItemClick ShowDetailCommand"
        local:MvxItemTemplate="@layout/customlayout" />
</LinearLayout>

as you can see above i have called my customlayout inside the listview layout

Below is my ViewModelClass

public class ListViewModel : BaseViewModel
    {
    public IListService ListService { get; set; }

    private MvxCommand _acceptCommand;
    private ListAcceptedResult _accepted;
    private MvxCommand _detailsCommand;        
    private ObservableCollection<MyCustomClass> _myList = new ObservableCollection<MyCustomClass>();

    public ListViewModel(IListService listService)
    {
        ListService = listService;

    }
    public ObservableCollection<MyCustomClass> MyList
    {
        get { return _myList; }
        set
        {
            _myList = value;
            RaisePropertyChanged(() => MyList);
        }
    }

    public ListAcceptedResult Accepted
    {
        get { return _accepted; }
        set
        {
            _accepted = value;
            RaisePropertyChanged(() => Accepted);
            Update();
        }
    }             

    public ICommand AcceptCommand
    {
        get
        {
            IsLoading = true;
            return
                new MvxCommand<MyCustomClass>(
                    item =>
                        //On Success assigning the returned value from service to Accepted Property,
                            error => { IsLoading = false; ReportError(error.Message); }));
        }
    }       



    public async System.Threading.Tasks.Task Update()
    {
        //update logic
    }
}

But i am not able to bind the AcceptCommand command to my button.

i am aware that this will not work because inside my customlayout view i do not get the AcceptCommand command as it is not a part of object MyCustomClass

please help me with some example.

Thanks in advance

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

As you know, data binding works by binding directly to the current ViewModel/Model. You're not able to access properties or commands of the parent view model, unless you provide a property to access the parent.

Anyway, one option is to create a value converter that you use in your binding. This converter will return a MvxCommand object that when executed will use MvxMessenger to publish a message.

The parent view model will subscribe to this message and then execute the command that you want.

I've created a sample based on Stuart Lodge's N=02 example.

https://github.com/kiliman/MvxCommandToMessage

EDIT: I modified the sample to use a generic MessageToCommandValueConverter. You can now pass in the message type in the binding. You still need specific message types though since MvxMessenger.Publish() is global to your app. See the code on GitHub for the changes.


Here's the value converter:

public class KittenAcceptedMessageValueConverter : MvxValueConverter<Kitten, ICommand>
{
    protected override ICommand Convert(Kitten kitten, Type targetType, object parameter, CultureInfo culture)
    {
        return new MvxCommand(() =>
        {
            var messenger = Mvx.Resolve<IMvxMessenger>();
            var message = new KittenAcceptedMessage(this, kitten);
            messenger.Publish(message);
        });
    }
}

And here's how you bind to it in your layout. Use . to pass the current object to the converter.

<Mvx.MvxImageView
    android:layout_width="75dp"
    android:layout_height="75dp"
    android:layout_margin="10dp"
    local:MvxBind="ImageUrl ImageUrl; Click KittenAcceptedMessage(.)" />

And then finally in your ViewModel, you would subscribe to this message, and call your command:

_messenger.Subscribe<KittenAcceptedMessage>(message => 
{
     KittenAcceptedCommand.Execute(message.Kitten); 
});

private MvxCommand<Kitten> _kittenAcceptedCommand;
public ICommand KittenAcceptedCommand
{
    get
    {
        _kittenAcceptedCommand = _kittenAcceptedCommand ?? new MvxCommand<Kitten>(kitten =>
        {
            var toast = Mvx.Resolve<IToastPlugin>();
            toast.Show(string.Format("You accepted {0}", kitten.Name));
        });
        return _kittenAcceptedCommand;
    }
}

Hope this helps.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...