Reputation: 57
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
Reputation: 5768
I think you can take a look to this sample:
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
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