none
how to write in a richtextbox from another class RRS feed

  • Question

  • Hello,

    I am currently developing a winforms application. I have a Form1 where I put a richtextbox.
    I would like to display text in this richtextbox from anywhere in my application code.
    For example, in the richTextBox of Form1, I would like to be able to write in this richTextBox from another class called Process.

    I thought to set the public field for richTextBox in the designer of Form1 and directly assign a text in this richTextBox in the Process class, but it does not work.

    Would you have a simple code example to write to a richTextBox from another class (not Form), please?

    Thanks.
    • Edited by speed780 Tuesday, June 30, 2020 11:14 PM
    Tuesday, June 30, 2020 11:14 PM

All replies

  • If nothing else, you can create a public function in the Form1 class that accepts a text string and copies it into the rich text box.

    Tim Roberts | Driver MVP Emeritus | Providenza & Boekelheide, Inc.

    Wednesday, July 1, 2020 2:55 AM
  • Hi speed780,

    Thank you for posting here.

    If they are in the same project, you can also do it like this:

        class Process
        {
            public void WriteToRTB() 
            {
                RichTextBox t = Application.OpenForms["Form1"].Controls["richTextBox1"] as RichTextBox;
                t.Text = "value";
            }
        }

    Best Regards,

    Timon


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, July 1, 2020 6:07 AM
  • Thanks, but it does not work. Morevover, I would like to add text in richTextBox. I would like to add text to the continuation like a log in the richtextbox.

    Do you have a simple example to do that?

    Thanks.


    • Edited by speed780 Wednesday, July 1, 2020 8:37 AM
    Wednesday, July 1, 2020 8:29 AM
  • I tried it, bit it does not work, the reference is not detected. Moreover, I would like to add text to the continuation like a log in the richtextbox.

    Do you know a solution for that?

    Thanks.

    Wednesday, July 1, 2020 8:38 AM
  • Hi,

    It works well when I test.

    I created a new form2, and then called this class in the code of form2 to add text to RichTextBox in form1.

    The following is the complete code after modification.

        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                new Form2().ShowDialog();
            }
        }
       

        class Process
        {
            public void WriteToRTB(string value)
            {
                RichTextBox t = Application.OpenForms["Form1"].Controls["richTextBox1"] as RichTextBox;
                t.Text = t.Text + Environment.NewLine + value;
            }
        }

            public Form2()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                Process process = new Process();
                process.WriteToRTB(textBox1.Text);
                this.Close();
            }

    Best Regards,

    Timon


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, July 1, 2020 8:46 AM
  • Thank you for your reply.

    In fact, I have an issue with the line :

    RichTextBox t = Application.OpenForms["Form1"].Controls["richTextBox1"] as RichTextBox;

    I have a System.NullReferenceException in this line. My form and richTextBox have different name.

    The name of my Form is MainForm and the name of the richTextBox is boxLog. I replaced it and I have the exception.

    RichTextBox t = Application.OpenForms["MainForm"].Controls["boxLog"] as RichTextBox;

    Do you know why?

    Thanks.

    Wednesday, July 1, 2020 9:26 AM
  • This is not a good approach. It too tightly couples your code together. If you later want to change to a different control or even write to someplace else you'd need to adjust your code. In my experience it is always wrong to expose a control of a form directly from the form. It is far too limiting. There are better solutions.

    My guess is that this is an output style window where you're writing messages. If so then model it as such. Create a logger or output interface that any code can use to write to the "output" (or use one of the many existing ones available already). Alternatively you could use events but an interface is probably better here.

    public interface IOutput
    {
        //TODO: Add whatever methods you want here
        void WriteMessage ( string message );
    }

    Then implement the interface backed by a control. Note that since the request can come from any thread your code needs to ensure requests are marshaled to the UI thread.

    public class TextBoxOutput : IOutput
    {
        public TextBoxOutput ( TextBoxBase control )
        {
            _control = control;
        }
    
        public void WriteMessage ( string message )
        {
            if (_control.InvokeRequired)
                _control.Invoke((OutputMessage)WriteMessage, message);
            else //TODO: Add newline if desired...
                _control.AppendText(message);
        }
    
        private delegate void OutputMessage ( string message );
    
        private readonly TextBoxBase _control;
    }


    Now the hard part is hooking everything up. Normally we would use DI and/or IoC to get the dependencies set up but you can go the poor man's route by using a static class instead.

    //TODO: Simple approach to getting access to the output, alternatives include dependency injection or IoC
    public static class Outputs
    {
        public static AggregateOutput Default { get; } = new AggregateOutput();
    }

    The challenge in your case is that you're trying to hook up an output that could go away later and/or you may have multiple ones so creating a helper aggregate output seems beneficial. This is what is exposed from the static class above for convenience. It really is just another implementation of the output interface.

    public class AggregateOutput : IOutput
    {
        //Simple registration logic
        public void AddOutput ( IOutput output ) => _outputs.Add(output);
    
        public void WriteMessage ( string message )
        {
            foreach (var output in _outputs)
                output.WriteMessage(message);
        }
    
        private readonly List<IOutput> _outputs = new List<IOutput>();
    }

    Now in the form that has the control you can add the output when the form loads which allows it to get the output. In a real app you should also ensure you remove the output before the form goes away to prevent errors but I'll leave that as an exercise.

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
    
        protected override void OnLoad ( EventArgs e )
        {
            base.OnLoad(e);
    
            //Add the current form's control to the output
            //TODO: In a real app you should unhook the control when the form unloads...
            Outputs.Default.AddOutput(new TextBoxOutput(richTextBox1));
        }
    
        private void button1_Click ( object sender, EventArgs e )
        {
            var message = textBox1.Text;
            if (!String.IsNullOrEmpty(message))
                //Using a static class here to keep it simple
                Outputs.Default.WriteMessage(message);
        }
    }
    In the above code the output is registered when the form is loaded. The button handler is an example of how you might call it anywhere in your app, not just in the form itself. This is where the DI, IoC, static class stuff would come in.


    Michael Taylor http://www.michaeltaylorp3.net

    Wednesday, July 1, 2020 1:49 PM
    Moderator
  • hi

    The open forms object can access in other words the instantiated class members can access  .

     MainForm obj = new MainForm();
                obj.Show();
                RichTextBox t = Application.OpenForms["MainForm"].Controls["BoxLog"] as RichTextBox;
                t.Text = "somet texrt";

    Thanks and Regards

    laxmidhr sahoo

    Wednesday, July 1, 2020 4:33 PM
  • Here is another idea which is discussed in this article. In short, this method sends a string to a broadcasting class via an Interface and sends in this case a string to any form which has subscribed to the listener.

    namespace BroadCasting.Interfaces
    {
        public interface IMessageListener
        {
            void OnListen(string message);
        }
    }
    

    broadcasting class

    using System.Collections.ObjectModel;
    using System.Windows.Forms;
    using BroadCasting.Interfaces;
    
    namespace BroadCasting.Classes
    {
        public class Broadcaster
        {
            private readonly Collection<IMessageListener> listeners = 
                new Collection<IMessageListener>();
    
            /// <summary>
            /// Send text
            /// </summary>
            /// <param name="message">text to send</param>
            /// <param name="sender">Form which is sending a message</param>
            /// <remarks></remarks>
            public void Broadcast(string message, Form sender)
            {
                foreach (IMessageListener listener in listeners)
                {
                    listener.OnListen(message);
                }
            }
            /// <summary>
            /// Send text
            /// </summary>
            /// <param name="message">text to send</param>
            public void Broadcast(string message)
            {
                foreach (IMessageListener listener in listeners)
                {
                    listener.OnListen(message);
                }
            }
    
            /// <summary>
            /// Add a Listener to the Collection of Listeners
            /// </summary>
            /// <param name="listener"></param>
            public void AddListener(IMessageListener listener)
            {
                listeners.Add(listener);
            }
            /// <summary>
            /// Remove a Listener from the collection
            /// </summary>
            /// <param name="listener"></param>
            public void RemoveListener(IMessageListener listener)
            {
    
                for (int index = 0; index < listeners.Count; index++)
                {
                    if (listeners[index].Equals(listener))
                    {
                        listeners.Remove(listeners[index]);
                    }
                }
            }
        }
    }

    namespace BroadCasting.Classes
    {
        public static class Factory
        {
            private static Broadcaster _broadcaster;
    
            public static Broadcaster Broadcaster()
            {
                return _broadcaster ?? (_broadcaster = new Broadcaster());
            }
        }
    }

    For each form listening the form implements IMessageListener eg.

    public partial class Form2 : Form, IMessageListener

    Must include a static using statement,

    using static BroadCasting.Classes.Factory;

    In the form new constructor add the form to the collection in Broadcaster class.

    public Form2()
    {
        InitializeComponent();
        Broadcaster().AddListener(this);
        Closing += Form2_Closing;
    }

    In closing event remove the form from the collection.

    private void Form2_Closing(object sender, CancelEventArgs e)
    {
        Broadcaster().RemoveListener(this);
    }

    Implement OnListen for IMessageListener interface

    public void OnListen(string message)
    {
        richTextBox1.Text = richTextBox1.Text + $"{message}";
    }

    To send a message from another form, in this case SendTextBox is a TextBox on the form sending a string.

    Broadcaster().Broadcast($" {SendTextBox.Text}\n");


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    Wednesday, July 1, 2020 5:47 PM
    Moderator
  • Hi,

    Has your issue been resolved?

    If so, please click on the "Mark as answer" option of the reply that solved your question, so that it will help other members to find the solution quickly if they face a similar issue.

    Best Regards,

    Timon


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Thursday, July 16, 2020 9:11 AM