-
Notifications
You must be signed in to change notification settings - Fork 2
clickable controls
Many controls that come with MAUI, like Labels, do not have Click events built in. However, these controls do support GestureRecognizers, including the TapGestureRecognizer. With some fancy extension method magic and generic control type, a BindClick bindable property can be added where the tap gesture is automatically created during the bind process. Then the extension method can add this BindClick call to any and all controls that allow gesture recognizers. This approach can be done for any control type and any gesture if needed. The BindClick is the only one that currently ships with Shield MVVM, but it gives an invaluable example of how to hook everything up. Here is the code needed to hook everything up as a full example:
A generic control wrapper type:
public class ClickableControl<T>
where T : BindableObject, IGestureRecognizers
{
public static readonly BindableProperty CommandProperty =
BindableProperty.Create(
nameof(ClickableControl<T>),
typeof(ICommand),
typeof(ClickableControl<T>),
propertyChanged: OnCommandPropertyChanged);
private ClickableControl() { }
static void OnCommandPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
var control = (T)bindable;
var command = (ICommand)newValue;
var classId = nameof(ClickableControl<T>);
var gestureRecognizer = new TapGestureRecognizer() { ClassId = classId };
gestureRecognizer.Tapped += (s, e) =>
{
if (command != null && command.CanExecute(null))
command.Execute(null);
};
foreach (var gesture in control.GestureRecognizers
.Where(a => a is TapGestureRecognizer tap && tap.ClassId == classId))
{
control.GestureRecognizers.Remove(gesture);
}
control.GestureRecognizers.Add(gestureRecognizer);
}
}
Extension method(s) added for BindingHelper to call (Need one per each control that need to be exposed):
namespace CoreBTS.Maui.ShieldMVVM;
public static partial class ControlBindExtensionMethods
{
public static Bindings.BindableProperty<ICommand> BindClick(this Label _) => new(Controls.ClickableControl<Label>.CommandProperty);
}
In code-behind binding, can now BindClick to a label:
Binder.WithControl(SecondaryLabel)
.Once(c => c.BindClick(), vm => vm.SomeCommand)
.For(c => c.BindText(), vm => vm.Secondary.MyLabel);