0

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

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 в классе, чтобы это работало?

aepot
  • 49,560
  • Это winforms или wpf? Если да, то есть другой способ. А с ref ничего не получится. – aepot May 08 '22 at 13:16
  • А как это сделать с помощью свойств? Изменю название вопроса, поскольку на момент написания забыл как называются свойства – Титан May 08 '22 at 13:18
  • Я дам решение, если скажете тип прилодения. – aepot May 08 '22 at 13:19
  • 1
    это winforms, добавлю тег – Титан May 08 '22 at 13:20
  • @AlexF Несуществующую функцию? Это какую? А data binding выглядит подходяще. Если я правильно понимаю, то если я добавлю SomeTextbox.DataBindings.Add("Text", foo.Value, "Name");, изменение текста текстбокса повлечет за собой изменение foo.Value, так? – Титан May 08 '22 at 13:32
  • @Титан вот только не надо пытаться передать foo.Value в биндинг по значению, это не может работать! И откуда вы вообще взяли "Name"? – Pavel Mayorov May 08 '22 at 13:35

1 Answers1

2

Через 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 я рассматривал здесь.

aepot
  • 49,560
  • Спасибо, и это также изменит data.Value при вводе пользователем текста в текстбокс (если привязать данные к текстбоксу)? – Титан May 08 '22 at 13:52
  • @Титан совершенно верно, изменит. Но я не помню, по какому именно событию, скорее всего по лост-фокусу. В WPF это настраивается, в винформах - не помню. – aepot May 08 '22 at 13:53