I have this form in my Xamarin.Forms application where I have two buttons, that are both meant to update a boolean value. Depending on whether that value is true or false, I want only one of the buttons to be enabled. Think of them as a "door": one button sets the "exit" boolean to true and the other to "false". So when the "enter" button is clicked I want it to be disabled until the user "exits" by clicking the "exit" button.
CanExecute/ChangeCanExecute should be the way to go here, at least by my own knowledge - and that's what I've tried. But it doesn't seem to be working, even when I abstract that functionality on a simpler content page.
I have attached a sample of my ViewModel's code, simplified for clarity.
I can't understand why I'm stumped by something that is so simple outside of MVVM conventions.
public bool _hasWorkerExit;
public bool hasWorkerExit
{
get { return _hasWorkerExit; }
set
{
_hasWorkerExit = value;
OnPropertyChanged();
EnterCommand?.ChangeCanExecute();
ExitCommand?.ChangeCanExecute();
}
}
public Command EnterCommand => new Command(SendWorkerEntry,WorkerCanEnter());
public Command ExitCommand => new Command(SendWorkerExit,WorkerCanExit());
private Func<bool> WorkerCanEnter()
{
return new Func<bool>(() => hasWorkerExit);
}
private Func<bool> WorkerCanExit()
{
return new Func<bool>(() => !hasWorkerExit);
}
private void SendWorkerEntry()
{
// Do the work you're meant to do
hasWorkerExit = false;
}
private void SendWorkerExit()
{
// Do the work you're meant to do
hasWorkerExit = true;
}
Here's the .xaml code for the buttons
<dxe:SimpleButton Grid.Column="0"
FontSize="13"
Text="Enter"
BorderThickness="0"
BackgroundColor="{StaticResource ButtonColour}"
PressedBackgroundColor="{StaticResource PressedButtonColour}"
TextColor="{StaticResource ButtonTextColour}"
PressedTextColor="{StaticResource ButtonTextColour}"
DisabledBackgroundColor="{StaticResource DisabledButtonColour}"
CornerRadius="0"
CornerMode="Round"
Command="{Binding EnterCommand}"></dxe:SimpleButton>
<dxe:SimpleButton Grid.Column="1"
FontSize="13"
Text="Exit"
BorderThickness="0"
BackgroundColor="{StaticResource ButtonColour}"
PressedBackgroundColor="{StaticResource PressedButtonColour}"
TextColor="{StaticResource ButtonTextColour}"
PressedTextColor="{StaticResource ButtonTextColour}"
DisabledBackgroundColor="{StaticResource DisabledButtonColour}"
CornerRadius="0"
CornerMode="Round"
Command="{Binding ExitCommand}"></dxe:SimpleButton>
CodePudding user response:
You can try:
Button 1:
IsEnabled="{Binding HasWorkerExit}"
Button 2:
IsEnabled="{Binding HasWorkerExit, Converter={Helpers:InverseBoolConverter}}"}"
One property alone should solve your problem.
public bool _hasWorkerExit;
public bool HasWorkerExit
{
get { return _hasWorkerExit; }
set
{
_hasWorkerExit = !_hasWorkerExit;
OnPropertyChanged();
}
}
Invert Helper code:
public class InverseBoolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return !((bool)value);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value;
//throw new NotImplementedException();
}
}
CodePudding user response:
Try this instead of using the Func<bool>
, you can use a simple method group for the Commands which should suffice:
public Command EnterCommand => new Command(SendWorkerEntry, WorkerCanEnter);
public Command ExitCommand => new Command(SendWorkerExit, WorkerCanExit);
private bool WorkerCanEnter() => hasWorkerExit;
private bool WorkerCanExit() => !hasWorkerExit;
Alternatively, this should also work:
public Command EnterCommand => new Command(SendWorkerEntry, () => hasWorkerExit);
public Command ExitCommand => new Command(SendWorkerExit, () => !hasWorkerExit);