1

I want to bind a button's IsEnabled to the result of a boolean expression.

I only find quite complex solutions using converters or other methods. Is it also possible in a more simple way?

Example code:

<Button IsEnabled="{ Binding Path=IsRecordingEnabled }" />
public partial class MainWindow : Window
{
    public bool IsRecording { get; set; } = false;
    public string LoggingFolder { get; set; } = null;

    public bool IsRecordingEnabled
    {
        get
        {
            return !IsRecording && LoggingFolder != null;
        }
    }

    // ...
}

Obviously the Button is not updating when the expression changes. I understand that I need to notify the GUI via OnNotifyPropertyChanged or similar. But how to do that in my case where I want to handle the boolean expression which has no set method but is changed via the composition of IsRecording and LoggingFolder.

3 Answers 3

2

You'll have to invoke the PropertyChanged event when you change either IsRecording or ReplayLogFile. In the event args, you have to tell that the property IsRecordingEnabled changed:

public partial class MainWindow : Window,INotifyPropertyChanged
{
    private bool _isRecording = false;;
    public bool IsRecording
    {
     get => _isRecording;
     set
     {
         _isRecording = value;
         PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsRecordingEnabled)));
     }

    private string _replayLogFile = null;
    public string ReplayLogFile
    {
       get => _replayLogFile;
       set
       {
           _replayLogFile = value;
           PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsRecordingEnabled)));
       }
    }

    public bool IsRecordingEnabled
    {
        get
        {
            return !IsRecording && LoggingFolder != null;
        }
    }

    // ...
}
Sign up to request clarification or add additional context in comments.

1 Comment

Perfect, I'm using a mixture of this answer and MindSwipe's answer.
1

The de-facto default implementation of PropertyChanged is:

protected void OnPropertyChanged([CallerMemberName] string name = null)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}

You can see it has the parameter name decorated with the attribute [CallerMemberName] it "Allows you to obtain the method or property name of the caller to the method." (source). Which means that you can manually specify which property changed by passing in the name. This means you can tell the GUI a property changed, without having to have a setter and set it. Like so:

private bool _isRecording = false;

public bool IsRecording
{
    get => _isRecording;
    set
    {
        _isRecording = value;
   
        // You could omit the next line, if the UI doesn't bind to this property
        OnPropertyChanged();
        OnPropertyChanged(nameof(IsRecordingEnabled));
    }
}

Comments

0

You can use a ToggleButton instead of a button.

WPF:

<ToggleButton x:Name="record" Content="Record" .../>

In Main Window you can use: record.IsChecked = true/false; to set or reset the state of the ToggleButton

if (record.IsChecked == true && LoggingFolder == null)
{
    //Do what you want
}

You can also use a click event

private void record_Click(object sender, RoutedEventArgs e)
{
    LoggingFolder != null;
}

1 Comment

Thanks for the hint regarding ToggleButton. A perfect improvement for my use-case. However updating the GUI, I want to use a 'declarative' approach instead of the 'imparative' u're suggesting.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.