So, I found some similar questions but it didn't help me to solve my problem. Since it's the first time using Xamarin.Forms, I made the error of not using ViewModels so I'm moving all the methods to viewmodels. As I think I understood, TextChanged is an event and not a BindableProperty so what I'm doing won't work.
I'm checking regex to validate an email based on TextChanged. This is the code:
<controls:StandardEntry x:Name="email" Text="{Binding Email}" TextChanged="{Binding ValidateEmail}"/>
public void ValidateEmail(object sender, TextChangedEventArgs e)
{
if (RegexUtils.ValidEmail().IsMatch(email))
{
// do stuff
}
else
{
// do stuff
}
}
You cannot move TextChanged
to a viewmodel. It belongs in the view itself.
[OPINION] It is a valid technique to have everything in the view, not have a viewmodel. Only make a viewmodel if you have a reason to do so.
If you do make a viewmodel, that doesn't mean EVERYTHING moves to it. The idea of MVVM is that a view operates on Data; that data goes in the VM.
Methods that only need the Data, that don't refer to View Elements, can (optionally) move to the VM.
Some events can be converted to commands. Thus Button Click event can be replaced by a Command in viewmodel. Its a judgement call whether to use Click in code-behind, or Command in viewmodel. Use whichever is more convenient, given what you need the method to do.
However an event handler such as TextChanged is inherently part of the functioning of its view element. It stays in View. It stays because it uses event arg properties, to allow manipulation of the text element.
[FOR CONVENIENCE] To make access to VM convenient, define a property in your view's code behind:
MyViewModel VM => (MyViewModel)BindingContext;
Then to access a VM property:
... VM.SomeProperty ...
So if TextChanged previously was able to use SomeProperty
directly, because it was in the view, change that to VM.SomeProperty
everywhere in TextChanged.