JonathanK
JonathanK

Reputation: 57

Bind button in DataTemplate C#

I'm trying to bind a button in a DataTemplate that is being used by a collection view. This is my button inside the DataTemplate, and I want to bind it to a command in "DetailDayPageViewModel".

        Button viewComment = new Button()
        {
            TextColor = Color.DodgerBlue,
            HorizontalOptions = LayoutOptions.Start,
            VerticalOptions = LayoutOptions.Start,
            FontSize = 16
        };
        // this binding does not work
        viewComment.SetBinding(Button.CommandProperty, nameof(DetailDayPageViewModel.ViewComment));

Upvotes: 1

Views: 704

Answers (2)

Alessandro Caliaro
Alessandro Caliaro

Reputation: 5768

I think you can take a look to this sample:

TestBinding

It refers to a ListView, but it should be applicated to a CollectionView.

You need to set the the "source":

        TapGestureRecognizer tgrUpDown2 = new TapGestureRecognizer();
        tgrUpDown2.SetBinding(TapGestureRecognizer.CommandProperty, new Binding("BindingContext.UpDown2Command", source: this));
        tgrUpDown2.SetBinding(TapGestureRecognizer.CommandParameterProperty, ".");

then in your Model, you have the "parameter" passend...

  this.UpDown2Command = new Command(async (object obj) =>
        {

            try
            {
                if (_isTapped)
                    return;

                if (obj != null)
                    System.Diagnostics.Debug.WriteLine("Obj is not null");
                else
                    System.Diagnostics.Debug.WriteLine("Obj IS null");


                _isTapped = true;

                int idx = List.IndexOf((Model)obj);

                List[idx].Checked1 = !List[idx].Checked1;

                _isTapped = false;

            }
            catch (Exception ex)
            {
                _isTapped = false;
                await Application.Current.MainPage.DisplayAlert("Attention", ex.Message, "Ok");
            }
        });

This is a useful link I have found some years ago:

listview-in-xamarin-forms-in-mvvm

If you want a "class" to define your ViewCell, you can assign the class in this way:

        lv.ItemTemplate = new DataTemplate(() =>
        {
            return new MyViewCell(lv);
        });

Where MyViewCell is something like:

    class MyViewCell : ViewCell
    {

        public MyViewCell(ListView lv)
        {
            StackLayout slView = new StackLayout();
            slView.SetBinding(StackLayout.BackgroundColorProperty, "BackgroundColor");

            Label lDesc = new Label();
            lDesc.SetBinding(Label.TextProperty, "Description", stringFormat: "DESCRIPTION: {0}");
            lDesc.SetBinding(Label.TextColorProperty, "TextColor");

            // LABEL QTY
            TapGestureRecognizer tgrQty = new TapGestureRecognizer();
            tgrQty.SetBinding(TapGestureRecognizer.CommandProperty, new Binding("BindingContext.QtyCommand", source: lv));
            tgrQty.SetBinding(TapGestureRecognizer.CommandParameterProperty, ".");

.... ....

            View = slView;

        }

    }

You can pass "ListView" in the constructor so you can use it in "source" binding property.

Upvotes: 0

Nikhileshwar
Nikhileshwar

Reputation: 1684

Use RelativeBinding for binding values of Page's BindingContext to property inside DataTemplate.

There are two ways to do this:

1: Binding through the ViewModel. ReltiveBinding of Mode FindAncestorBindingContext

public class ItemView : Grid
{
    public ItemView()
    {
        Button clickButton = new Button() { Text = "Hi there" };
        clickButton.SetBinding(
            Button.CommandProperty,
            new Binding(
                "ItemClickCommand",
                source: new RelativeBindingSource(
                    RelativeBindingSourceMode.FindAncestorBindingContext,
                    typeof(ViewModel))
                ));

        this.Children.Add(clickButton);
    }
}

2: Binding through the Parent view BindingContext:

public class ItemView : Grid
{
    public ItemView()
    {
        Button clickButton = new Button() { Text = "Hi there" };
        clickButton.SetBinding(
            Button.CommandProperty,
            new Binding(
                "BindingContext.ItemClickCommand",
                source: new RelativeBindingSource(
                    RelativeBindingSourceMode.FindAncestor,
                    typeof(CollectionView))
                ));

        this.Children.Add(clickButton);
    }
}

Please do check and see if it helps!! Comment for any queries.

Upvotes: 2

Related Questions