Reputation: 7449
I want to disable the send button if any of the three entries is empty, but how that can be achieved in an MVVM fashion?
I thought of the CanExecute delegate, but how can I fire it whenever the TextChanged fired?
Also if I opt in the behaviors, how can I communicate with other controls like button if I'm using Behavior<Entry>
This is the view:
<ContentPage.Content>
<AbsoluteLayout>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="56"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="10"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="*"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<Label Text="Contact Us" FontSize="Medium" Grid.ColumnSpan="3"/>
<Entry Text="{Binding ContactData.message_name}" x:Name="subject" Grid.Row="2" Grid.Column="1" Placeholder="Subject"/>
<Entry Keyboard="Email" Text="{Binding ContactData.receiver_email}" x:Name="email" Grid.Row="3" Grid.Column="1" Placeholder="Email"/>
<Editor Text="{Binding ContactData.message_subject}" x:Name="body" Grid.Row="4" Grid.Column="1" />
<Button Grid.Row="5" Grid.Column="1" Command="{Binding ContactFormSent}" Text="Send"/>
</Grid>
</AbsoluteLayout>
</ContentPage.Content>
in the ViewModel:
public ContactViewModel()
{
ContactFormSent = new RelayCommand(SendContactInfo);
ContactData = new ContactModel();
}
private bool CanSend() //this only get called when the view model is constructed
{
return !(string.IsNullOrWhiteSpace(ContactData.receiver_email) && string.IsNullOrWhiteSpace(ContactData.message_subject) &&
string.IsNullOrWhiteSpace(ContactData.message_name));
}
In the Behavior option, I wan it to be used with both Entry
and Editor
, so is my way to go is the Behavior
class, not the generic version? if so, then how can I implement it?
Upvotes: 4
Views: 9627
Reputation: 13601
Usually, in order to react to a view event using MVVM pattern, it is recommended that you use EventToCommandBehaviour.
But in this case it is not needed, as the setters on properties bound to Entry
should trigger every time text changes. You can use that to trigger ChangeCanExecute()
on command to notify view that the button can now be enabled/disabled.
For e.g.:
string _firstName;
public string FirstName
{
get { return _firstName; }
set
{
if (_firstName != value)
SendCommand.ChangeCanExecute();
SetProperty(ref _firstName, value, nameof(FirstName));
}
}
string _lastName;
public string LastName
{
get { return _lastName; }
set
{
if (_lastName != value)
SendCommand.ChangeCanExecute();
SetProperty(ref _lastName, value, nameof(LastName));
}
}
string _email;
public string Email
{
get { return _email; }
set
{
if (_email != value)
SendCommand.ChangeCanExecute();
SetProperty(ref _email, value, nameof(Email));
}
}
Command _sendCommand;
public Command SendCommand
{
get
{
return _sendCommand ?? (_sendCommand = new Command(OnSend, CanSend));
}
}
bool CanSend(object obj)
{
return Validate();
}
void OnSend(object obj)
{
if(Validate())
{
//actual button click execution
}
}
bool Validate()
{
// disable button if any entry empty
return !string.IsNullOrEmpty(_firstName)
&& !string.IsNullOrEmpty(_lastName)
&& !string.IsNullOrEmpty(_email);
}
Upvotes: 4
Reputation: 537
Command
has a public method ChangeCanExecute()
.
When you new a Command
, you could specify the canExecute
condition. Once your TextChanged
event is triggered, call the ChangeCanExecute()
method.
Example:
Command someCommand = new Command(
() => SomeMethod(),
()=> { return CanSend(); }
);
Once a Button
changed a text:
private void TextChanged(object sender, TextChangedEventArgs e)
{
ViewModel.someCommand.ChangeCanExecute();
}
Upvotes: 1