I am designing an instant messanger and I am using tabs to allow for multiple chats to be taking place in the same windows form.
When a new chat is opened, a new tab is added, using a User Control to make the new tab contain all of the required text boxes, buttons etc...

static public void AddChat(uint chatID)
        {
            tabChats.BeginInvoke(new AddTabDelegate(AddTab), new object[] { chatID });
        }

        private delegate void AddTabDelegate(uint chatID);

        private static void AddTab(uint chatID)
        {
            TabPage tab = new TabPage(chatID.ToString());
            tab.Controls.Add(new ChatControl(chatID, serverStream));
            tabChats.TabPages.Add(tab);
        }

My problem is that i need to write messages to a rich text box inside the User Control which is inside the new TabPage.

Can anyone help me?

I assume that the rich text box is contained in your custom ChatControl.
If that is the case then it is with this object that you need to interact.
If you add a message property to your ChatControl

public string MessageText
{
    get { return this.richTextBox1.Text; }
    set { this.richTextBox1.Text = value; }
}

then the main form can access the rich text box.

Alternatively, you could code the message handling inside the ChatControl object.

Hi,
When I try and access the public property of my ChatControl from the form containing the tabs I am try to access the property using

tabChats.TabPages[0].Controls[0].OutputWindow

which isn't allowed because C# knows that a Control added to the tab's doesn't have to be my own ChatControl.

Is there any way to force TabPage.Controls.Add() to only accept my ChatControl class?
Or would that be going about this the wrong way?

Cheers,
J Keegan

Fixed,
For others reference all you have to do it cast the TabPage.Control as the custom control.

That's one way.
Or you could keep a separate array or collection of your custom controls that can be referenced without casting.

I did consider a seperate list of the custom controls, but there are 2 big problems with doing this :(
If you update a property in the seperate list, it wont update on the screen the user is looking at.
The custom controls consume twice the memory.

But nevertheless, having to cast it does seem a little crude :(

If the memory use is doubled then are you in fact creating the control twice.
Passing the same parameters to a constructor does not mean you have the same object;
just another copy of the object that works with the same values.

This code creates two ChatControl objects.

List<ChatControl> chatControls = new List<ChatControl>();
        private static void AddTab(uint chatID)
        {
            TabPage tab = new TabPage(chatID.ToString());
            // add NEW chat control to tab
            tab.Controls.Add(new ChatControl(chatID, serverStream));
            tabChats.TabPages.Add(tab);
            // add NEW chat control to local store
            chatControls.Add(new ChatControl(chatID, serverStream));
        }

This code create one ChatControl object and stores a reference to it in two places.

List<ChatControl> chatControls = new List<ChatControl>();
        private static void AddTab(uint chatID)
        {
            TabPage tab = new TabPage(chatID.ToString());
            // get NEW chat control
            ChatControl newControl = new ChatControl(chatID, serverStream);
            // add chat control to tab
            tab.Controls.Add(newControl);
            tabChats.TabPages.Add(tab);
            // add chat control to local store
            chatControls.Add(newControl);
        }

It is also sometimes necessary to force a control to refresh itself when a property changes.
This is done by invalidating the control.

public string MessageText
{
    get { return this.richTextBox1.Text; }
    set 
    {
        this.richTextBox1.Text = value; 
        this.Invalidate(); //<-- force this control to repaint
    }
}
This question has already been answered. Start a new discussion instead.