I'm building an app as a prototype to test positioning of components on different tabpages. I will end up with several textboxes, several radio buttons and several listboxes, etc. Some of these components will be positioned on tabpage1 and others on tabpage2.
My plan is to make visible those components that will show on tabpage1 and hide the rest. Then show the others on tabpage2 and hide those shown on tabpage1. The reason I'm not just adding the target components to the target tabpage is because my tabpages will be dynamic and I won't know ahead of time how many there will be so I have to create the tabpages dynamically.
Please consider that:
0. the very nature of how a TabControl works is that you see only the Controls on the selected TabPage, so I can't imagine why you would need to think about showing, or hiding, Controls in the way you've described. Each TabPage can have its own EventHandlers for many of the usual things every Control handles, like MouseDown, but TabPages cannot have their own individual handlers for Events like KeyPress.
0.a. it is possible to actually move Controls from one TabPage to another; it's a hack, and I've done it myself just an experiment, but I can't see any practical use for it, and it invites complications, imho.
1. a TabControl sited on a Form has Size, Location, BoundingBox, DisplayRectangle, and ClientRectangle, Properties that you can inspect, and those will all be in Form co-ordinate space.
2. within the TabControl, each TabPage will have the identical Size, Location, DisplayRectangle, etc., values: they are all located in the co-ordinate space of the TabControl.
2.a. you have some access to the structure of the Tab object that decorates the "virtual top" of each TabPage, which will be mentioned below.
3. you can resize the TabControl itself, and all the TabPages will resize, but, you can
never change the size of an individual TabPage so it is different from that of any other TabPage.
3a. you could, through whatever means reduce the effective visible size of a TabPage by whatever means (black panels ?), but that's an odd idea, and probably will lead to a bizarre experience for the user: fugeddabouttit.
I'm trying to develop the understanding of how to position a component (I'm starting with just a button) in relation to a tabcontrol. If I can figure that out, then I can position it on any tabpage, at any position within that tabpage.
0. learning about positioning is a good thing. among the important things you'll want to focus on are:
a. understanding how to map points and rectangles from a Form's co-ordinate system to the Screen's co-ordinate system, and to a Control's co-ordinate system, and the reverse, is a very good thing. you need to master these:
a.1. PointToScreen, PointToClient
a.2. RectangleToScreen, RectangleToClient
1. Here you need to clarify to me, or distinguish for yourself, the difference between positioning a Control which is
in the ControlsCollection of a Form, and a Control which is i
n the ControlCollection of a TabPage.
2. If you want to make some Control, in a Form, be on top of a TabControl and TabPage: yes, you
could do that, and, yes, you can determine the relative location of each TabPage
as it is selected by using the GetTabRect(SelectedIndex) method of the TabControl (look it up), and move a Control on a Form around based on which TabPage is selected.
3. But, having a Control on the Form on top-of a TabControl, or moving around on the Form to align itself with which TabPage is selected as the selected TabPage changes is: a really "crazy" design idea :) I can show you code for how to do that, but I seriously advise you not to implement this type of Control relationship unless there is some compelling "organic" reason to do so (I can't imagine one, but, who knows ?).
I was told by a c# developer not to put controls on tabpages directly, but to put them on the form and then move them onto the tabpage when you need them.
0. I can't guess what the intent of the advice given to you was, but I see every reason for you to put the Controls on each TabPage necessary for each TabPage, and I can't see any reason why they should be on the Form first, and then added at
design-time to the TabPages. If every TabPage needs the same bunch of Controls, just set them at design-time on one TabPage, and get them looking like you want them, and then copy them, and paste them, into all the other TabPages: worst case is you'll have to move the pasted in Controls as a group to get them aligned where you want them thanks to Visual Studio having its own ideas about where to paste things.
1. perhaps your advisor was thinking of the situation where, at run-time you need to created new Controls on certain TabPages, on one TabPage, or on all TabPages ? That is possible.
~
Let's consider the issues in adding a Control to a TabPage at run-time:
0. you know every TabPage will have the same co-ordinate space, with 0,0 at upper-left.
1. you know that every Control already on the TabPage has position, size, etc. Properties you can access to know exactly where it is in TabPage co-ordinate space.
2. as an example, let's consider that you want to place a new Button on every TabPage at run-time, and you wanted it to be at a different y position on each TabPage based on some variable you defined, but at a fixed x location.
private Button btnToBeAdded;
private int btnXLocation = 30;
private int btnStartYLocation = 30;
private int btnYOffset = 40;
private void addButtonsToTabPages_Click(object sender, EventArgs e)
{
for (int i = 0; i < tabControl1.TabPages.Count; i++)
{
btnToBeAdded = new Button();
btnToBeAdded.BackColor = Color.AliceBlue;
btnToBeAdded.Name = "addedBtn" + i.ToString();
btnToBeAdded.Text = "click Me";
btnToBeAdded.Tag = i;
tabControl1.TabPages[i].Controls.Add(btnToBeAdded);
btnToBeAdded.Location = new Point(btnXLocation, btnStartYLocation + (btnYOffset * i));
btnToBeAdded.Click += btnToBeAdded_Click;
}
}
private void btnToBeAdded_Click(object sender, EventArgs e)
{
Button btnClicked = sender as Button;
switch (Convert.ToInt32(btnClicked.Tag))
{
case 0:
firstTabPageButtonDoSomething();
break;
case 1:
break;
case 2:
break;
default:
throw new IndexOutOfRangeException();
}
}
private void firstTabPageButtonDoSomething()
{
MessageBox.Show("Button on first TabPage clicked");
}
Discussion: note how the Tag Property of each Button added to each TabPage was set to a numeric value that identified the index of the TabPage in the TabControl.
Then, all Buttons added can share the same 'Click EventHandler: in that EventHandler by using the Tag Property ... had to convert it to an integer because a Tag Property is of type Object ... you can then trigger execution of whatever you want each Button to do.