If I un-comment out those 2 lines(under MenuItem click event), which creates 2 instances of TabPage and RichTextBox, everything works as I want.
Когда вы раскомментируете эти строки, вы снова добавляете тот же экземпляр расширенного текстового поля и вкладки на панель контейнера, что не имеет смысла.Вместо этого добавьте новые элементы управления foreach tabpage.(Надеюсь, это требование)
Now my first question is why do I have to make new instances of only those 2 types(TabPage, RichTextBox) again but not TabControl?
TabControl - это родительский элемент управления, в котором TabPages являются дочерними элементами управления.Вы можете иметь несколько вкладок под одним TabControl.Поэтому вам не нужно создавать TabControls, кроме tbcEditor
, который вы уже добавили.Мы не добавляем элементы управления контейнером более одного раза (если это не требуется).Нужно ли нам больше форм?Нет, только одна форма, которая может содержать все дочерние элементы управления правильно.Точно так же только один TabControl, который может содержать коллекцию TabPages.Вам понадобится больше TabControls, только если вы хотите, чтобы вложенные вкладки были для каждой новой вкладки, что, я думаю, не является обязательным требованием.
But I can't access rtb since it is declared as local.
Это не имеет большого значения.Вы можете сделать это двумя способами:
1) Поиск нужного элемента управления с помощью цикла.Свойство SelectedTab дает то, что вы хотите.
private void someEvent(object sender, EventArgs e)
{
foreach (Control c in tbcEditor.SelectedTab.Controls)
{
if (c is RichTextBox)
{
Clipboard.SetDataObject(((RichTextBox)c).SelectedText);
break; //assuming u have just one main rtb there
}
}
}
2) При создании каждого тега добавьте rtb в tabPage, а затем вы можете получить элемент тега на выбранной вкладке дляполучить расширенное текстовое поле.Я бы пошел на этот подход.
Редактировать: (В общем, пожалуйста, внесите следующие изменения в свой код):
TabControl tbcEditor = new TabControl();
private void frmTextEditor_Load(object sender, EventArgs e)
{
Controls.Add(tbcEditor);
tbcEditor.Dock = DockStyle.Fill;
AddMyControlsOnNewTab();
}
private void AddMyControlsOnNewTab()
{
TabPage tbPage = new TabPage();
RichTextBox rtb = new RichTextBox();
tbPage.Tag = rtb; //just one extra bit of line.
tbcEditor.TabPages.Add(tbPage);
tbPage.Controls.Add(rtb);
rtb.Dock = DockStyle.Fill;
}
private void newToolStripMenuItem_Click(object sender, EventArgs e)
{
AddMyControlsOnNewTab();
}
Теперь вы можете вызвать еговот так:
private void someEvent(object sender, EventArgs e)
{
RichTextBox rtb= (RichTextBox)tbcEditor.SelectedTab.Tag;
Clipboard.SetDataObject(rtb.SelectedText);
//or even better in just a line,
//Clipboard.SetDataObject(((RichTextBox)tbcEditor.SelectedTab.Tag).SelectedText);
}
Здесь вы должны рассмотреть, какой именно контроль вы получаете первым, а какой - нет.В любом случае вы получите TabPage, но не RichTextBox.Поэтому вы должны пометить RichTextBox на TabPage.Вы должны разыграть его, так как Tag
имеет тип объекта, поэтому вы должны указать, какой это тип объекта.Наконец, этот метод имеет то преимущество, что вам не нужно перебирать список, поэтому он более производительный.И что у вас может быть больше RichTextBoxes в TabPage (при условии, что вы хотите скопировать текст только из одного набора RichTextBoxes, по одному из каждой TabPage) ..