Simple ContentPage with a lot of buttons on it. I want a single event handler (OnButtonPress
) to decode which button was pressed and take a variety of actions. Instead of tediously writing Clicked="OnButtonPress"
a hundred times in the XAML, I thought (as I had defined a custom Button2:Button class anyway, for different reasons) to define this event handler as standard for the Button2 class.
Is there a way to do this? I've been searching and AI-ing for days, and can't seem to figure this one out, so would appreciate a pointer.
I've tried:
<Style />
, but events are not bindable.public EventHandler Clicked = "OnButtonPress"
in the Button2 class, but it cannot implicitly convert type String to System.EventHandler.this.Clicked += new EventHandler(MainPage.OnButtonPress);
in the Button2 class, but it complains about how OnButtonPress
doesn't exist in MainPage, when it clearly does.OnButtonPress
into the Button2 class, but then it complains about "the type or namespace OnButtonPress could not be found" (it's like... right there, dude).this.Clicked = OnButtonPress();
this.Clicked += OnButtonPress(object sender, EventArgs e);
The general structure of the code is simple:
namespace Adam
{
public partial class MainPage : ContentPage
{
public void OnButtonPress(object sender, EventArgs e)
{
// decoding stuff goes here
}
public class Button2 : Button
{
// lotsa properties and stuff added here
public Button2()
{
// I didn't put any code in here
}
}
}
}
and the XAML (I omitted all the grids and other stuff):
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Adam"
x:Class="Adam.MainPage"
BackgroundColor="Black">
<local:Button2 Text = "Test" />
>
So after more decades of research, I gave up trying to override the method, and instead turned to Commanding. Which I didn't want to do, originally, because of all the extra code I had to write.
First off, I created my custom button class outside my MainPage class:
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
}
public class Button2 : Button
{
// stick variables in here
}
Then, I created a AdamViewModel
class:
public class AdamViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public ICommand ButtonCommand { private set; get; }
public AdamViewModel()
{
ButtonCommand = new Command<string>(
execute: (string arg) =>
{
// Button logic goes here
RefreshCanExecutes();
},
canExecute: (string arg) =>
{
return true;
});
}
void RefreshCanExecutes()
{
(ButtonCommand as Command).ChangeCanExecute();
}
Next up, I went to MainPage.xaml
and added this section:
<ContentPage.BindingContext>
<local:AdamViewModel />
</ContentPage.BindingContext>
Then, in my custom button, I added CommandParameter="A0"
and similar such code to the rest of my buttons.
Finally, in Styles.xaml
, I added code to style the button, and also the command:
<Style TargetType="{x:Type local:Button2}">
<Setter Property="TextColor" Value="White" />
<Setter Property="BorderColor" Value="DimGrey" />
<Setter Property="BorderWidth" Value="1" />
<Setter Property="Margin" Value="3,0,3,0" />
<Setter Property="Padding" Value="0" />
<Setter Property="BackgroundColor" Value="Black" />
<Setter Property="MinimumHeightRequest" Value="1" />
<Setter Property="CornerRadius" Value="4" />
<Setter Property="Command" Value="{Binding ButtonCommand}" />
</Style>
Note that last Setter, that binds the button to my single button processor/decoder logic.
Which (sigh, exhausted breaths) finally got to the functionality I was trying to achieve - one single function to rule them all, and not writing so explicitly in the XAML a hundred times.
I guess that it's not necessary to do a view-model class, in retrospect, but at least things are working now, and the view-model is kind of useful anyway for other stuff.