I want to use Tap Gesture Recogniser with ICommand meaning using the ViewModel instead of the code behind.
I am making the gesture recogniser work through the code behind as shown below
HomePage.xaml
<CollectionView Margin="10,0,10,0"
ItemSizingStrategy="MeasureAllItems"
ItemsLayout="VerticalList"
VerticalScrollBarVisibility="Always"
ItemsSource="{Binding QuestionPacks}">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="model:QuestionPack">
<Frame Margin="5"
CornerRadius="10">
<Frame.GestureRecognizers>
<TapGestureRecognizer
Tapped="TapGestureRecognizer_Tapped"/>
<TapGestureRecognizer
NumberOfTapsRequired="2"
Tapped="TapGestureRecognizer_Tapped_1"/>
</Frame.GestureRecognizers>
<VerticalStackLayout Margin="5">
<Label Text="{Binding Topic}" />
<Label Text="{Binding TopicId}" />
</VerticalStackLayout>
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
Please note the x:DataType=model:QuestionPack
in the DataTemplate.
HomePage.xaml.cs
private async void TapGestureRecognizer_Tapped(object sender, EventArgs e)
{
var selectedItem = ((VisualElement)sender).BindingContext as QuestionPack;
if (selectedItem == null)
return;
LoadingQuestions.IsRunning = true;
LoadingQuestions.IsEnabled = true;
await Shell.Current.GoToAsync($"{nameof(QuestionsPage)}?topicSelected={selectedItem.TopicId}");
LoadingQuestions.IsRunning = false;
LoadingQuestions.IsEnabled = false;
}
This is working fine but I want to know how to implement this in my ViewModel. I came across 2 challenges while trying to do this.
I am supposed to use Command instead of Tapped under the TapGestureRecognizer. Whenever I bind the Command field to a Command in my code behind, the x:DataType="model:QuestionPack" raises a problem because the command is not defined in the model for the data template.
Even if applying the Command to the tap gesture recognizer wasn't causing building the app to fail, how am I to pass the object that is tapped into the code behind? In the code behind, I retrieve it using object sender but in the ViewModel, I don't know. I am guessing that that is where CommandParameters come into play but how to implement them is where I don't know.
And not to be a bother, if one can explain what CommandParameter="{Binding .}"
means too.
Any assistance is greatly appreciated.
CodePudding user response:
Create you ViewModel file and define as BindingContext Example
<ContentPage.BindingContext>
<vm:MyViewModel />
</ContentPage.BindingContext>
Then define your Command and ICommand in your ViewModel( suposing that you know how to do )
And in your xaml file, you can do something like this
<Frame.GestureRecognizers>
<TapGestureRecognizer NumberOfTapsRequired="1"
CommandParameter="{Binding .}"
Command="{Binding
Source={RelativeSource AncestorType={x:Type vm:MyViewModel}}, Path=TapGestureRecognizer_Tapped}"/>
</Frame.GestureRecognizers>
Tell me for more details