marcel
marcel

Reputation: 25

Bind GUI element property to boolean expression - WPF GUI

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.

Upvotes: 1

Views: 376

Answers (3)

Rquente
Rquente

Reputation: 3

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;
}

Upvotes: 0

MindSwipe
MindSwipe

Reputation: 7855

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));
    }
}

Upvotes: 1

SomeBody
SomeBody

Reputation: 8743

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;
        }
    }

    // ...
}

Upvotes: 2

Related Questions