Während eines Prototypworkshops fragte mich ein Kunde kürzlich, warum das Xamarin.Forms Label
Steuerelement kein Click
oder Tap
Ereignis veröffentlicht.
Die Antwort darauf ist relativ einfach:
Die meisten Xamarin.Forms Steuerelemente veröffentlichen selbst kein Click
oder Tap
Ereignis. Stattdessen nutzt man in einem solchen Fall einen Tap Gesture Gesture Recognizer.
Über Tap Gesture Recognizer kann so ziemliches jedes Steuerelement klickbar gemacht werden.
Klicks / Taps mit Event Handlern
In einem kleinen Beispiel sieht das ganze wie folgt aus:
<ContentPage.Content>
<StackLayout>
<Label x:Name="NumberOfClicksLabel"></Label>
<Label Text="Klick mich!">
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="KlickMichTapped"/>
</Label.GestureRecognizers>
</Label>
</StackLayout>
</ContentPage.Content>
Im Quelltext definiere ich zunächst ein StackLayout, das zwei Labels beherbergt. Das obere der beiden Labels stellt später die Anzahl der Klicks dar, auf das untere wird zum Hochzählen geklickt. Wie man im Beispiel sieht, besitzt das Label eine Eigenschaft GestureRecognizer
. Bei dieser Eigenschaft handelt es sich um eine Auflistung von registrierten Gesten. Der TapGestureRecognizer
, über den das Label klickbar gemacht wird, wird einfach zur GestureRecognizer Auflistung hinzugefügt. Anschließend wird noch definiert, dass das Ereignis Tapped
durch die Methode KlickMichTapped
behandelt wird.
Die Methode KlickMichTapped
befindet sich im Code-Behind meiner Seite:
public partial class MyPage : ContentPage
{
public MyPage()
{
InitializeComponent();
}
private int _numberOfClicks = 0;
private void KlickMichTapped(object sender, EventArgs e)
{
_numberOfClicks++;
NumberOfClicksLabel.Text = $"{_numberOfClicks} Klicks";
}
}
Klicks / Taps, Commands und MVVM
Wer statt Code-Behind lieber das Model-View-ViewModel Muster einsetzt, kann natürlich auch hier TapGestureRecognizer
nutzen.
Das entsprechende ViewModel dazu sieht so aus:
public class TapDemoViewModel : INotifyPropertyChanged
{
public Command TapCommand { get; set; }
public TapDemoViewModel()
{
TapCommand = new Command(() => OnTapped());
}
private void OnTapped()
{
NumberOfClicks++;
}
private int _numberOfClicks;
public int NumberOfClicks
{
get { return _numberOfClicks; }
set
{
OnPropertyChanged();
_numberOfClicks = value;
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Innerhalb des ViewModels werden das Command TapCommand
definiert sowie die Eigenschaft NumberOfClicks
. Für das TapCommand
wird die Methode OnTapped
hinterlegt. Diese erhöht den Wert der Eigenschaft NumberOfClicks
.
Im XAML Code wird nun an die Eigenschaft Text
des ersten Labels die Eigenschaft NumberOfClicks
des ViewModels gebunden. Das im ViewModel definierte Command TapCommand
wird wiederum an die Eigenschaft Command
des TapGestureRecognizer
gebunden.
<ContentPage.Content>
<StackLayout>
<Label Text="{Binding NumberOfClicks, StringFormat='{0} Klicks'}}">
</Label>
<Label Text="Klick mich">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding TapCommand}" />
</Label.GestureRecognizers>
</Label>
</StackLayout>
</ContentPage.Content>
Die Verbindung zwischen ViewModel und View wird schlussendlich im Code Behind des Views über die Zuweisung der Eigenschaft BindingContext
erledigt.
public partial class TapDemo : ContentPage
{
public TapDemo()
{
InitializeComponent();
BindingContext = new TapDemoViewModel();
}
}
In Aktion sieht die App dann wie folgt aus:
Fazit
Wie wir in diesem Beitrag gesehen haben, kann mit der Hilfe eines TapGestureRecognizer
so ziemliches jedes Oberflächenelement unter Xamarin.Forms mit einem Click / Tap Ereignis ausgestattet werden. Neben dem TapGestureRecognizer
gibt es übrigens auch noch den Pinch Gesture Recognizer und den Pan Gesture Recognizer