0

I am doing a simple test and can't seem to get the button binding to work correctly. I am trying to simply disable a button based on the value of a textbox. In this example, if the value of the textbox = 1 the button needs to be disabled. Although I have Prism installed for this example, I still couldn't get it to work correctly by directly implementing IPropertyNotifyChanged.

public class LoginModel : BindableBase
{
    private string _username;

    public string Username
    {
        get { return _username; }
        set { _username = value; RaisePropertyChanged(); }
    }

}

public class LoginViewModel : BindableBase
{
    private LoginModel _model;

    public LoginModel Model
    {
        get { return _model; }
        set { _model = value; RaisePropertyChanged(); }
    }


    public DelegateCommand ButtonTest { get; private set; }

    public LoginViewModel()
    {
        _model = new LoginModel { Username = "test" };
        ButtonTest = new DelegateCommand(Click, CanClick);
    }

    private void Click()
    {
        MessageBox.Show(_model.Username);
    }

    private bool CanClick()
    {
        if (_model.Username == "1")
        {
            return false;
        }
        return true;
    }

LoginView.xaml
    <Grid>
        <StackPanel>
            <TextBox Height="25" Width="100" Text="{Binding Path=Model.Username, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
            <Button Height="25" Width="100" Content="Click Me" Command="{Binding Path=ButtonTest}"/>
        </StackPanel>
    </Grid>

The textbox binding is correctly working and the CanClick() method correctly returns false if _model.Username == "1" however how can I get the UI to update to correctly disable the button?

wamaral
  • 71
  • 1
  • 14
  • For `CanExecute()` to be called, the `ICommand.CanExecuteChanged` event has to be raised. Depending on your implementation of `DelegateCommand`, this may or may not happen "semi-automatically", i.e. where that implementation implements the event by subscribing to `CommandManager.RequerySuggested`. But note that even in that case, `RequerySuggested` is raised only in specific scenarios, which may not include yours. There are cases where you have to either force that event to be raised explicitly by calling `CommandManager.InvalidateRequerySuggested()` or raising the event ... – Peter Duniho Jun 05 '21 at 02:53
  • ... directly from your `ICommand` implementation. For what it's worth, I gave up on `CommandManager` a long time ago, and design my code always to raise `CanExecuteChanged` explicitly when dependent properties are modified. I find this much more reliable _and_ more efficient (because it only raises the event for the command that actually needs it, whereas going through `CommandManager` causes _all_ of your commands to re-query their state). – Peter Duniho Jun 05 '21 at 02:53
  • See duplicate for details about `CommandManager`. – Peter Duniho Jun 05 '21 at 02:53

0 Answers0