Привязать свойство элемента GUI к логическому выражению — графический интерфейс WPF

#c# #wpf #xaml

#c# #wpf #xaml

Вопрос:

Я хочу привязать кнопку IsEnabled к результату логического выражения.

Я нахожу только довольно сложные решения с использованием конвертеров или других методов. Возможно ли это более простым способом?

Пример кода:

 <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 amp;amp; LoggingFolder != null;
        }
    }

    // ...
}
  

Очевидно, что кнопка не обновляется при изменении выражения. Я понимаю, что мне нужно уведомить графический интерфейс через OnNotifyPropertyChanged или аналогичный. Но как это сделать в моем случае, когда я хочу обработать логическое выражение, которое не имеет set метода, но изменяется с помощью композиции IsRecording и LoggingFolder .

Ответ №1:

Вам придется вызывать PropertyChanged событие при изменении либо IsRecording или ReplayLogFile . В аргументах события вы должны указать, что свойство IsRecordingEnabled изменилось:

 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 amp;amp; LoggingFolder != null;
        }
    }

    // ...
}
  

Комментарии:

1. Отлично, я использую смесь этого ответа и ответа MindSwipe.

Ответ №2:

Фактическая реализация по умолчанию PropertyChanged :

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

Вы можете видеть, что у него есть параметр name , украшенный атрибутом [CallerMemberName] , который «Позволяет вам получить имя метода или свойства вызывающего метода». (источник). Это означает, что вы можете вручную указать, какое свойство было изменено, передав имя. Это означает, что вы можете сообщить GUI, что свойство изменено, без необходимости устанавливать и устанавливать его. Вот так:

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

Ответ №3:

Вместо кнопки можно использовать переключатель.

WPF:

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

В главном окне вы можете использовать:
запись.IsChecked = true / false; для установки или сброса состояния кнопки переключения

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

Вы также можете использовать событие щелчка

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

Комментарии:

1. Спасибо за подсказку относительно ToggleButton . Идеальное улучшение для моего варианта использования. Однако, обновляя графический интерфейс, я хочу использовать «декларативный» подход вместо «импаративного», который вы предлагаете.