Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Xamarin.Forms button in ViewCell. How to handle the event?

I have a custom ViewCell with a button. When I click this button I would like to handle this click in the ContentPage which displays the ListView with the ViewCells. In iOS, I would do this with a delegate from the Cell. How would I do this in C# / Xamarin.Forms?

This is my custom ViewCell:

    public CustomCell ()
    {
        button = new Button ();

        button.Text = "Add";
        button.VerticalOptions = LayoutOptions.Center;

        button.Clicked += [WHAT DO DO HERE???];

        var nameLabel = new Label ();
        nameLabel.SetBinding (Label.TextProperty, "name");
        nameLabel.HorizontalOptions = LayoutOptions.FillAndExpand;
        nameLabel.VerticalOptions = LayoutOptions.Center;

        var viewLayout = new StackLayout () {
            Padding = new Thickness (10, 0, 10, 0),
            Orientation = StackOrientation.Horizontal,
            Children = { nameLabel, button }
        };

        View = viewLayout;
    }

And my ContentPage which is using this as a ViewCell looks like this:

ListView.ItemTemplate = new DataTemplate (typeof(CustomCell));

So, how do I catch the button press?

Please ask if you need clarification.


Ok, so I got this up atleast:

This is my ContentPage:

    ...
    ListView.ItemTemplate = new DataTemplate (() => new CustomCell (CustomCellButtonClicked));
}

void CustomCellButtonClicked (CustomCell m, EventArgs e)
{
    //How do I get my associated object here?!

    System.Diagnostics.Debug.WriteLine ("Pressed cell " + m.ToString ());
}

And this is my cell:

    public EventArgs e = null;
    public event ButtonClickEvent ClickListener;
    public delegate void ButtonClickEvent (AddCardCell m, EventArgs e);

    public CustomCell (ButtonClickEvent Listener)
    {
        ClickListener += Listener;
        customButton = new Button ();

        customButton.Text = "Add";
        customButton.VerticalOptions = LayoutOptions.Center;

        customButton.Clicked += AddButtonClicked;

        ...
    }

    void AddButtonClicked (object sender, EventArgs e)
    {
        if (ClickListener != null) {
            ClickListener (this, e);
        }
    }

So, all that is left now is to get the actual object associated with the cell. In ItemSelected for ListView, it is done like this:

ListView.ItemSelected += async (object sender, SelectedItemChangedEventArgs e) => {
            var obj = (HSObject)e.SelectedItem;
        };

How can I do something like this?


Got it! This is perhaps not a good solution, but it seems to work:

void CustomCellButtonClicked (CustomCell m, EventArgs e)
{
    var myObject = m.BindingContext;
}

I will accept the only answer due to the fact that it pushed me in the right direction. (And that it's probably a better way to do this).

like image 933
ullstrm Avatar asked Sep 22 '14 14:09

ullstrm


1 Answers

If you are using a view model or some other class, you can pass it into your cell and make your calls from there. The list view also currently overrides the buttons on your cell with the ItemSelected event from the list view. Luckily they put in an override on the data template.

private readonly ViewModel _model;
public CustomCell (ViewModel model)
{
    _model = model; <--- Your DI foo
    BindingContext = model; <---

    button = new Button ();

    button.Text = "Add";
    button.VerticalOptions = LayoutOptions.Center;

    button.Clicked += (sender, args) => _model.DoSomething(); <---- Your action

    var nameLabel = new Label ();
    nameLabel.SetBinding (Label.TextProperty, "name");
    nameLabel.HorizontalOptions = LayoutOptions.FillAndExpand;
    nameLabel.VerticalOptions = LayoutOptions.Center;

    var viewLayout = new StackLayout () {
        Padding = new Thickness (10, 0, 10, 0),
        Orientation = StackOrientation.Horizontal,
        Children = { nameLabel, button }
    };

    View = viewLayout;
}

Then you can pass your class/view model into your cell with an anonymous function.

ListView.ItemTemplate = new DataTemplate (() => new CustomCell(viewModel));

This way you can trigger your event from the view cell, and handle it somewhere else (view model).

like image 96
jcc Avatar answered Nov 10 '22 23:11

jcc