Как связать значение свойства/поля класса с свойством контрола?

Я хочу поместить ссылку на строку в класс

public class MyClass {
    public ref string Value; //компилятор говорит, что так нельзя
    //...
}

чтобы сделать так:

MyClass foo = new();
foo.Value = ref SomeTextbox.Text;
SomeTextbox.Text = "something" //допустим, пользователь что-то вводит
MessageBox.Show(foo.Value) //"something"

В моём случае, области видимости (и, соответственно, время жизни) текстбокса и моего класса одинаковы. Поэтому, хотелось бы задать Value в качестве ссылки на текстбокс. Можно ли это сделать? Я знаю об альтернативных решениях с использованием:

  • Обработчиков событий TextChanged или LostFocus
  • Tag

но мне просто интересна сама возможность использования ссылки внутри класса, как правильно её внутри класса объявлять и как назначать. И если поле другого класса совсем невозможно использовать в качестве ссылки, то вопрос всё равно актуален – как тогда поместить ссылку на TextBox.. или вообще любую другую (текстбокс здесь для примера) внутрь динамического класса?

Например foo.Value = ref SomeExampleString – как я должен объявить Value в классе, чтобы это работало?


Ответы (1 шт):

Автор решения: aepot

Через ref не получится, так как свойство контрола не является полем. Получится через привязку данных.

Сначала надо реализовать интерфейс INotifyPropertyChanged, например в базовом классе.

public class NotifyPropertyChanged : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

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

Теперь код вашего класса изменить вот так

public class MyClass : NotifyPropertyChanged
{
    private string value;

    public string Value
    {
        get => value;
        set
        {
            this.value = value;
            OnPropertyChanged();
        }
    }
}

Создам форму, на которой будет Label и Button. Назначу 2 обработчика Form1.Load и Button.Click, получится вот такой код.

public partial class Form1 : Form
{
    private MyClass data;

    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        data.Value = DateTime.Now.ToString();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        data = new MyClass();
        label1.DataBindings.Add(nameof(Label.Text), data, nameof(MyClass.Value));
        // эквивалент label1.DataBindings.Add("Text", data, "Value");
    }
}

Теперь при изменении свойства Value у класса, текст в метке изменится автоматически.

введите сюда описание изображения

При этом не следует напрямую обращаться к label1.Text и не следует обращаться к полю value у класса с данными вне геттера и сеттера свойства Value. То есть из кода можно обращаться только к свойству MyClass.Value, тогда все привязанные к нему контролы будут своевременно обновляться.

Более сложные случаи привязок для Winforms я рассматривал здесь.

→ Ссылка