我正在使用标签功能创建一个简单的记事本类型的应用程序。我正在运行时创建TabControl,它的TabPages和RichTextBoxes。我让它们在类范围内实例化。还有一个名为New的MenuStrip项,通过单击可以添加更多标签页。
TabControl tbcEditor = new TabControl();
TabPage tbPage = new TabPage();
RichTextBox rtb = new RichTextBox();
private void frmTextEditor_Load(object sender, EventArgs e)
{
Controls.Add(tbcEditor);
tbcEditor.Dock = DockStyle.Fill;
tbcEditor.TabPages.Add(tbPage);
tbPage.Controls.Add(rtb);
rtb.Dock = DockStyle.Fill;
}
private void newToolStripMenuItem_Click(object sender, EventArgs e)
{
//TabPage tbPage = new TabPage();
//RichTextBox rtb = new RichTextBox();
tbPage.Controls.Add(rtb);
rtb.Dock = DockStyle.Fill;
tbcEditor.TabPages.Add(tbPage);
}
我面临的问题有点难以解释。我会尽力的。当表单加载时,一切都按预期工作。 TabControl使用添加了RichTextBox的TabPage创建。但是,如果我单击“新建”按钮添加另一个页面,它就会变得疯狂。创建了一个新的TabPage但没有添加RichTextBox。也没有错误。如果我取消注释掉那两行(在MenuItem点击事件下),它创建2个TabPage和RichTextBox实例,一切都按我的意思运行。
现在我的第一个问题是为什么我必须再次创建只有这两种类型(TabPage,RichTextBox)但不是TabControl的新实例?正如您在最后一行中所看到的,我可以再次使用tbcEditor
。但不是tbPage
和rtb
。
当然,我可以继续在当地范围内再次声明它们,但另一个问题就出现了。如果我想说,添加复制,粘贴功能,我应该这样做,对吗?
Clipboard.SetDataObject(rtb.SelectedText);
但我无法访问rtb
,因为它被声明为本地。
我对此感到非常困惑,所以对于如何克服这两个问题的任何建议和想法都将不胜感激。
谢谢。
答案 0 :(得分:2)
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下有多个选项卡。因此,除了已添加的tbcEditor
之外,您无需创建TabControls。我们不会多次添加容器控件(除非是它的要求)。我们需要更多表格吗?不,只有一种形式可以保持所有儿童控制权。类似地,只有一个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
是object类型,所以你必须指定它是哪种类型的对象。最后,这种方法的优点是您无需遍历列表,因此其性能更高。并且你可以在TabPage中有更多的RichTextBox(如果你只想从一组RichTextBox中复制文本,每个TabPage中有一个)。
答案 1 :(得分:0)
评论的行正在做他们想要做的事情。该代码不会将Richtextbox与Tabpage相关联。
TabPage tbPage = new TabPage(); // Creates a new tabpage
RichTextBox rtb = new RichTextBox(); // Creates a new RichtextBox control.
TabControl是一个容器,所以一个实例就可以了。
另见 - http://sujay-ghosh.blogspot.in/2009/03/addingremoving-dynamically-created.html,与tabcontrols无关,但如何动态创建控件。
希望这有帮助。
答案 2 :(得分:0)
代码
tbPage.Controls.Add(rtb);
rtb.Dock = DockStyle.Fill;
tbcEditor.TabPages.Add(tbPage);
获取现有文本框,将其添加到exisitng标签页,然后将现有标签页添加到编辑器中。由于这已经完成,没有任何反应。
当您添加这两行时,您可以创建文本框的新实例和新标签页,这正是您想要的。您的后一个问题来了,因为新声明的变量rtb
隐藏了在类中声明的变量 - 在另一个方法中,您只能访问类中声明的onde(除非将控件从选项卡中取出)
要解决无法访问正确文本框的问题,可以将它们保存在列表(*)(或其他一些集合)中,并参考与当前活动选项卡关联的文本框。为此,您必须创建一个事件侦听器,以查看当前激活的选项卡。
(*)而不是只有一个
答案 3 :(得分:0)
确定您需要创建RichTextBox rathere的新实例,而不是尝试将相同的实例添加到每个选项卡。
TabControl tbcEditor = new TabControl();
//Get rid off this line --- TabPage tbPage = new TabPage();
//Get rid off this line --- RichTextBox rtb = new RichTextBox();
List<TabPage> _tabs = new List<TabPage>();
List<RichTextBox> _tbx = new List<RichTextBox>();
private void frmTextEditor_Load(object sender, EventArgs e)
{
Controls.Add(tbcEditor);
tbcEditor.Dock = DockStyle.Fill;
AddNewTab();
}
private void newToolStripMenuItem_Click(object sender, EventArgs e)
{
AddNewTab();
}
private void AddNewTab()
{
//TabPage
var tbPage = new TabPage();
_tabs.Add(tbPage);
//RichTextBox
var rtb = new RichTextBox();
_tbx.Add(rtb);
tbPage.Controls.Add(rtb);
rtb.Dock = DockStyle.Fill;
tbcEditor.TabPages.Add(tbPage);
}
这只是将tab和rtb添加到可以通过索引访问的集合中(也可以使用Dictionary进行命名访问等)。当然还有其他方法,包括只需命名组件并在需要时循环使用等等。