[C#] TextBox и отдельный класс

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by Jakeroid, 4 Mar 2011.

  1. Jakeroid

    Jakeroid Member

    Joined:
    9 May 2009
    Messages:
    199
    Likes Received:
    12
    Reputations:
    1
    Есть ситуация:
    Класс, который выполняет необходимые мне функции. На форме есть ТекстБокс. Нужно, что бы функции класса, выводили в ТекстБокс значения.
    Каким способом это лучше сделать?
    Вариант типа:
    Textbox1.Text = имя_класса.имя_переменной;
    Не предлагать по следующим причинам:
    -Класс должен быть переносимым, что бы другой человек без особых изменений кода, мог подрубить свой текстБокс для этих целей.
    -В классе есть многопоточные функции, которые в своей работе на ходу должны выводить строки в ТекстБокс, например аналог делфи memo1.Lines.Add('bla');

    Как бы это реализовать на шарпе?
    .NET 4.0
     
  2. cupper

    cupper Elder - Старейшина

    Joined:
    6 Jun 2007
    Messages:
    369
    Likes Received:
    92
    Reputations:
    5
    а что мешает в класе сделать поле указывающее на этот (да впринцепи любой элемент в который можно текст вводить по типу ИЕТМ.text = ...) textbox ?

    и все действия по выводу информации скрыть в методах класса.

    А другой человек возьмет твой класс, создаст его объект, зарегистрирует в нем свой текст бокс, и будет работать с объктом класса, а инфа будет вываливать в этот текст бокс.
     
  3. Jakeroid

    Jakeroid Member

    Joined:
    9 May 2009
    Messages:
    199
    Likes Received:
    12
    Reputations:
    1
    Через указатели?
     
  4. Chrome~

    Chrome~ Elder - Старейшина

    Joined:
    13 Dec 2008
    Messages:
    936
    Likes Received:
    162
    Reputations:
    27
    В C# обекты класса и есть указателями.
     
  5. Jakeroid

    Jakeroid Member

    Joined:
    9 May 2009
    Messages:
    199
    Likes Received:
    12
    Reputations:
    1
    Точно, спасибо.

    Хм...
    Сделал в классе:
    Code:
    public TextBox Log;
    private void AddToLog(string data)
            {
                lock (Log)
                {
                    Log.Text = Log.Text + data; 
                }
            }
    В коде формы:
    Code:
    имя_объекта.Log = tbLog;
    Выдает ошибку:
    tbLog - это имя компонента на форме.
    М, как исправить?
     
    #5 Jakeroid, 4 Mar 2011
    Last edited: 4 Mar 2011
  6. GlooK

    GlooK Elder - Старейшина

    Joined:
    20 Apr 2007
    Messages:
    172
    Likes Received:
    53
    Reputations:
    10
    Юзай Control.Invoke при работе с GUI компонентами.
     
  7. Linkus

    Linkus Member

    Joined:
    20 Dec 2008
    Messages:
    168
    Likes Received:
    15
    Reputations:
    -1
    я чтото типо такого обычно пишу:
    Code:
    private void TextBoxUpdateText(string _text)
    {
        if(InvokeRequired)
        {
              this.Invoke(new Action<string>(TextBoxUpdateText),_text);
              return;
        }
      textBox1.text= _text;
    }
    
    это в классе формы)
     
  8. immortalist

    immortalist Member

    Joined:
    16 Jan 2010
    Messages:
    99
    Likes Received:
    64
    Reputations:
    37
    ну или вот так:
    Code:
    private void log(string s)
            {
                if (InvokeRequired) BeginInvoke(new Action(() => { logBox.AppendText(s + "\r\n"); }));
                else logBox.AppendText(s + "\r\n");
            }
    
     
  9. Linkus

    Linkus Member

    Joined:
    20 Dec 2008
    Messages:
    168
    Likes Received:
    15
    Reputations:
    -1
    только программисты меряются, у кого короче xD
     
    1 person likes this.
  10. W!z@rD

    W!z@rD Борец за русский язык

    Joined:
    12 Feb 2006
    Messages:
    973
    Likes Received:
    290
    Reputations:
    43
    Code:
    private void log(string s)
            {
                if (InvokeRequired) BeginInvoke(() => log(s));
                else logBox.AppendText(s + "\r\n");
            }
    
     
  11. Jakeroid

    Jakeroid Member

    Joined:
    9 May 2009
    Messages:
    199
    Likes Received:
    12
    Reputations:
    1
    А я вот, когда мне посоветовали юзать 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);
            }
     
    #11 Jakeroid, 6 Mar 2011
    Last edited: 6 Mar 2011
  12. BrainDeaD

    BrainDeaD Elder - Старейшина

    Joined:
    9 Jun 2005
    Messages:
    774
    Likes Received:
    292
    Reputations:
    214
    Почитай про делегаты.
    В данном случае делегат dAddToLog предаётся в метод Invoke.
     
  13. Jakeroid

    Jakeroid Member

    Joined:
    9 May 2009
    Messages:
    199
    Likes Received:
    12
    Reputations:
    1
    Я читал, все равно не понял зачем нужен Invoke в который передается делегат.
    Точнее я понимаю, потому что обращение к контролу идет из другого потока. Но в голове все равно логического понимания нету.

    Контролы закрыты для доступа из других потоков, и к ним доступ возможно осуществить только через делегат?
    Или это как то связано с прорисовкой?
     
  14. BrainDeaD

    BrainDeaD Elder - Старейшина

    Joined:
    9 Jun 2005
    Messages:
    774
    Likes Received:
    292
    Reputations:
    214
    Windows Forms Controls могут быть изменены только из потока, в котором они были созданы. invoke заставляет вызвать метод из потока GUI, а не текущего потока.
     
  15. Jakeroid

    Jakeroid Member

    Joined:
    9 May 2009
    Messages:
    199
    Likes Received:
    12
    Reputations:
    1
    to BrainDeaD
    Спасибо. Теперь прояснилось, как оно работает.
     
  16. CollapseTroll

    CollapseTroll New Member

    Joined:
    9 Nov 2015
    Messages:
    1
    Likes Received:
    0
    Reputations:
    0
    Привет всем!

    А если на время оставить 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 и наконец-то сделать по ООП-правильно. В случае консольного вывода мне ведь нафиг не нужно передавать в конструктор форму?..