C#-动态创建控件并访问它们
本文关键字:访问 控件 动态 创建 C#- | 更新日期: 2023-09-27 18:29:54
我正在创建一个带有选项卡功能的简单记事本类型的应用程序。我正在运行时创建TabControl、它的TabPages和RichTextBoxes。我在类范围内实例化了它们。还有一个名为"新建"的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单击事件下),这两行创建了TabPage和RichTextBox的两个实例,那么一切都可以按照我的意愿进行。
现在我的第一个问题是,为什么我必须再次只创建这两种类型(TabPage、RichTextBox)的新实例,而不创建TabControl?正如您在最后一行中看到的,我可以再次使用tbcEditor
。而不是CCD_ 2和CCD_。
当然,我可以在本地范围内再次声明它们,但随后出现了另一个问题。如果我想说,添加复制、粘贴功能,我应该这样做,对吧?
Clipboard.SetDataObject(rtb.SelectedText);
但是我不能访问rtb
,因为它被声明为本地的。
我对此感到非常困惑,所以任何关于如何克服这两个问题的建议和想法都将不胜感激。
谢谢。
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.
当您取消注释这些行时,您将再次向容器面板中添加同一个富文本框和选项卡页面实例,这毫无意义。相反,在每个选项卡页面上添加新控件。(我希望这是要求)
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中一个)。。
注释行正在做它们应该做的事情。代码不将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无关,而是如何动态创建控件。
希望这能有所帮助。
代码
tbPage.Controls.Add(rtb);
rtb.Dock = DockStyle.Fill;
tbcEditor.TabPages.Add(tbPage);
获取现有文本框,将其添加到现有选项卡页面,然后将现有选项卡页面添加到编辑器中。既然已经这样做了,什么也没发生。
当您添加这两行时,您将创建文本框的新实例和一个新的选项卡页,这正是您想要的。后一个问题出现了,因为新声明的变量rtb
隐藏了类中声明的变量——在另一种方法中,您只能访问类中声明(除非从选项卡中获得控制)的onde
为了避免无法访问正确的文本框,您可以将它们保存在列表(*)(或其他集合)中,并引用与当前活动选项卡关联的文本框。为此,您必须创建一个事件侦听器来查看当前激活了哪个选项卡。
(*)而不是只有一个
好吧,您需要在此处创建RichTextBox的新实例,而不是尝试向每个选项卡添加相同的实例。
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);
}
这只需将选项卡和rtb添加到可以通过索引访问的集合中(也可以使用Dictionary进行命名访问等)。当然,还有其他方法,包括命名组件并在需要时循环使用。