Есть ситуация: Класс, который выполняет необходимые мне функции. На форме есть ТекстБокс. Нужно, что бы функции класса, выводили в ТекстБокс значения. Каким способом это лучше сделать? Вариант типа: Textbox1.Text = имя_класса.имя_переменной; Не предлагать по следующим причинам: -Класс должен быть переносимым, что бы другой человек без особых изменений кода, мог подрубить свой текстБокс для этих целей. -В классе есть многопоточные функции, которые в своей работе на ходу должны выводить строки в ТекстБокс, например аналог делфи memo1.Lines.Add('bla'); Как бы это реализовать на шарпе? .NET 4.0
а что мешает в класе сделать поле указывающее на этот (да впринцепи любой элемент в который можно текст вводить по типу ИЕТМ.text = ...) textbox ? и все действия по выводу информации скрыть в методах класса. А другой человек возьмет твой класс, создаст его объект, зарегистрирует в нем свой текст бокс, и будет работать с объктом класса, а инфа будет вываливать в этот текст бокс.
Точно, спасибо. Хм... Сделал в классе: Code: public TextBox Log; private void AddToLog(string data) { lock (Log) { Log.Text = Log.Text + data; } } В коде формы: Code: имя_объекта.Log = tbLog; Выдает ошибку: tbLog - это имя компонента на форме. М, как исправить?
я чтото типо такого обычно пишу: Code: private void TextBoxUpdateText(string _text) { if(InvokeRequired) { this.Invoke(new Action<string>(TextBoxUpdateText),_text); return; } textBox1.text= _text; } это в классе формы)
ну или вот так: Code: private void log(string s) { if (InvokeRequired) BeginInvoke(new Action(() => { logBox.AppendText(s + "\r\n"); })); else logBox.AppendText(s + "\r\n"); }
Code: private void log(string s) { if (InvokeRequired) BeginInvoke(() => log(s)); else logBox.AppendText(s + "\r\n"); }
А я вот, когда мне посоветовали юзать Invoke нашел в гугле такое решение: Code: delegate void dAddToLog(string data); private void AddToLogCallback(string data) { Log.AppendText(data); } private void AddToLog(string data) { if (Log.InvokeRequired) { dAddToLog dAdd = new dAddToLog(AddToLogCallback); Log.Invoke(dAdd, new Object[]{data}); } else { Log.AppendText(data); } } Я не совсем понял как оно работает, кто бы смог объяснить. Сейчас попробую короткий вариант. Попробовал, юзаю это: Code: private void AddToLog(string s) { if (Log.InvokeRequired) Log.BeginInvoke(new Action(() => { Log.AppendText(s); })); else Log.AppendText(s); }
Я читал, все равно не понял зачем нужен Invoke в который передается делегат. Точнее я понимаю, потому что обращение к контролу идет из другого потока. Но в голове все равно логического понимания нету. Контролы закрыты для доступа из других потоков, и к ним доступ возможно осуществить только через делегат? Или это как то связано с прорисовкой?
Windows Forms Controls могут быть изменены только из потока, в котором они были созданы. invoke заставляет вызвать метод из потока GUI, а не текущего потока.
Привет всем! А если на время оставить invoke и делегаты и вернуццо к сабжу - как всё-таки правильней реализовать логгер на форме, если мне надо писать на форму из другого класса. Вот такой вариант есть у меня и он работает. но он imho блин неправильный с точки зрения архитектуры. Это класс логгера. Он содержит в себе экземпляр формы и конструктор, который инстанцирует эту форму(экземпляр логгера мы создадим на форме) Code: class MyLogger { private readonly Form1 form; public MyLogger(Form1 form) { this.form = form; } public void WriteSomeMessage() { this.form.LogStream = "Blah blah from MyLogger"; } } собсно форма. Форма содержит свойтсво которое пишет в сам контрол, и сторонний класс может к этому свойству достучаться(LogStream). ну и собсно всё, по кнопке вызывается WriteSomeMessage() стороннего класса-логгера, который пишет на форму Code: public partial class Form1 : Form { private MyLogger logger; public string LogStream { get { return this.tbLogger.Text; } set { this.tbLogger.AppendText(value + Environment.NewLine); } } public Form1() { InitializeComponent(); logger = new MyLogger(this); } private void buttonWrite_Click(object sender, EventArgs e) { logger.WriteSomeMessage(); } } Вообще у меня был класс логгера который писал к примеру в консоль, ULS, в текстовый файл. я просто закомментачивал ненужные методы. но cейчас хочу его прикрутить и в WinApp и наконец-то сделать по ООП-правильно. В случае консольного вывода мне ведь нафиг не нужно передавать в конструктор форму?..