I have a form page with text boxes and data grid view and other forms that contain a tab control. I want to add the first form tab in the second form. I tried to write the code for the form to appear but it is larger than the tab container and doesn't fit. Only half of the form appears.
This is my code:
private void tcMainPage_SelectedIndexChanged(object sender, EventArgs e)
{
if (tcMainPage.SelectedIndex == 0)
{
GTOWN.PrintingPage BookInfo = new PrintingPage();
BookInfo.TopLevel = false;
BookInfo.FormBorderStyle = FormBorderStyle.None;
BookInfo.Dock = DockStyle.Fill;
tpSearch.Controls.Add(BookInfo);
BookInfo.Show();
}
}
this is the form
and that is what appears
Set your main FORM as a Container.
yourForm.IsMdiContainer = true;
Then add the child form to the tabPage:
private void tcMainPage_SelectedIndexChanged(object sender, EventArgs e)
{
if (tcMainPage.SelectedIndex == 0)
{
PrintingPage newFrm = new PrintingPage
{
MdiParent = this,
// This set the form parent as the tabClicked
Parent = tcMainPage.TabPages[0]
};
newFrm.Show();
}
}
my tab form work good in the same code
thank you all my code was correct but the problem was in tab property i deleted the tab and add another one and the code is working now
thank you
I face this issue and I create this if may help
public void addform(TabPage tp, Form f)
{
f.TopLevel = false;
//no border if needed
f.FormBorderStyle = FormBorderStyle.None;
f.AutoScaleMode = AutoScaleMode.Dpi;
if (!tp.Controls.Contains(f))
{
tp.Controls.Add(f);
f.Dock = DockStyle.Fill;
f.Show();
Refresh();
}
Refresh();
}
Forms are top-most objects and cannot be placed inside of other containers.
You may want to refactor your code so that the items on your Form are on a UserControl instead. At that point you can then add that UserControl to both a Form and a TabControl
public UserControl myControl(){ /* copy your current view code here */}
public Form myForm(){
Controls.Add(new myControl());
}
public Form myTabbedForm(){
var tabControl = new TabControl();
var page1 = new TabPage();
page1.Controls.Add(new myControl());
tabControl.TabPages.Add(page1);
this.Controls.Add(tabControl);
}
Related
I'm having a main window (MainWindow.cs) form which contains a panel (pnlChild), I've created a new control to add my second form (Settings.cs) + controls to the panel:
Settings settings = new Settings() { Dock = DockStyle.Fill, TopLevel = false };
settings.FormBorderStyle = FormBorderStyle.None;
pnlChild.Controls.Add(settings);
settings.Show();
This is working fine, I have the same in my settings form, which also contains a panel "pnlChild", a child form (Appearance.cs) which contains "Appearance"
Settings.Appearance appearance = new Settings.Appearance() { Dock = DockStyle.Fill, TopLevel = false };
appearance.FormBorderStyle = FormBorderStyle.None;
pnlChild.Controls.Add(appearance);
appearance.Show();
Question: How can I change a text/update text to the "Settings" and/or "Main" form, when I press a button in the appearance child form?
Here is a workaround that maybe you can refer to. In this demo, I add textboxes named tbMain and tbSettings in MainWindows and Settings.
First, define a property in MainWindow.cs to access tbMain.
public TextBox TBM
{
get { return tbMain; }
set { tbMain = value; }
}
And define a property in Settings.cs to access tbSettings.
public TextBox TBS
{
get { return tbSettings; }
set { tbSettings = value; }
}
Then we can use Application.OpenForms Property to get the MainWindows and Settings instance. And modify the textbox value through the properties defined before.
private void btInAppearance_Click(object sender, EventArgs e)
{
Settings settings = (Settings)Application.OpenForms["Settings"];
settings.TBS.Text = "TextInSettings";
MainWindow main = (MainWindow)Application.OpenForms["MainWindow"];
main.TBM.Text = "TextInMainWindow";
}
I have a panel of labels, buttons and image that I wish to put into a flow layout panel.
As seen in some tutorial, I understand that it is possible to auto align new and additional buttons into a flow layout panel.
what I would like to ask is that is it possible to put a panel WITHIN a flow layout panel and call multiple instances of the same panel to appear within the flow layout panel.
My panel code would be
this.panelNotification.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.panelNotification.Controls.Add(this.button1);
this.panelNotification.Controls.Add(this.lblImage);
this.panelNotification.Controls.Add(this.lblName);
this.panelNotification.Controls.Add(this.lblLinkName);
this.panelNotification.Controls.Add(this.lblLinkLocation);
this.panelNotification.Controls.Add(this.lblLocation);
this.panelNotification.Location = new System.Drawing.Point(3, 3);
this.panelNotification.Name = "panelNotification";
this.panelNotification.Size = new System.Drawing.Size(506, 100);
this.panelNotification.TabIndex = 17;
So is it possible to include the whole panel into a flow layout panel? if yes, how do i do it. thank you.
Yes, you can put a Panel into a FlowLayoutoutPanel.
No, you can't put a control several times into a FlowLayoutoutPanel (in fact you can, but it is only displayed once).
But what you could do is writing some kind of Factory-Method that creates a new Panel with new Buttons/Labels/other Controls etc. every time you call it, and add these new instances to your FlowLayoutpanel. Something like this:
public class Form1
{
private Panel CreateNotificationPanel()
{
var p = new Panel { BackColor = Color.Red };
p.Controls.Add(new Button { Text = "Test" });
return p;
}
private void Form1_Load(System.Object sender, System.EventArgs e)
{
var flp = new FlowLayoutPanel { Dock = DockStyle.Fill };
flp.Controls.Add(CreateNotificationPanel());
flp.Controls.Add(CreateNotificationPanel());
flp.Controls.Add(CreateNotificationPanel());
this.Controls.Add(flp);
}
public Form1() { Load += Form1_Load; }
}
Another (and problably better) approach would be to create a UserControl that contains your Buttons/Labels/etc. instead of using a panel and adding all controls manually. Just create with the Designer and add new instances of the UserControl to the FlowLayoutPanel.
I am showing my MDI windows inside the main form but in one part of the splitter panel, like this:
Form2 f2= new Form2();
f2.MdiParent = this;
f2.Parent = this.splitContainer2.Panel2;
f2.Show();
but the problem is that I cannot cascade them if I write a code like this:
this.LayoutMdi(System.Windows.Forms.MdiLayout.Cascade);
"this" is the parent form. the main form.
Hoe can I cascade them?
thanks all.
You'll have to override the LayoutEngine for the SplitContainer panel. Microsoft has a good example here for creating a custom layout engine.
private void CascadeToolStripMenuItem_Click(object sender, EventArgs e) {
//LayoutMdi(MdiLayout.Cascade);
Rectangle bounding = this.splitContainer1.Panel1.DisplayRectangle;
Point nextFormLocation = bounding.Location;
foreach (Control c in this.splitContainer1.Panel1.Controls) {
if (!c.Visible) {
continue;
}
nextFormLocation.Offset(c.Margin.Left, c.Margin.Top);
c.Location = nextFormLocation;
c.BringToFront();
if (c.AutoSize) {
c.Size = c.GetPreferredSize(bounding.Size);
}
nextFormLocation.X = bounding.X + 20;
nextFormLocation.Y = bounding.Y + 20;
}
}
just add the above code to your cascade button and you'll get the basics of cascade.
I'm creating a multi-tabbed .NET application that allows the user to dynamically add and remove tabs at runtime. When a new tab is added, a control is added to it (as a child), in which the contents can be edited (eg. a text box). The user can perform tasks on the currently visible text box using a toolbar/menu bar.
To better explain this, look at the picture below to see an example of what I want to accomplish. It's just a mock-up, so it doesn't actually work that way, but it shows what I want to get done. Essentially, like a multi-tabbed Notepad.
View the image here: http://picasion.com/pic15/324b466729e42a74b9632c1473355d3b.gif
Is this possible in .NET? I'm pretty sure it is, I'm just looking for a way that it can be implemented.
You could use a simple extension method:
public static void PasteIntoCurrentTab(this TabControl tabControl)
{
if (tabControl.SelectedTab == null)
{
// Could throw here.
return;
}
if (tabControl.SelectedTab.Controls.Count == 0)
{
// Could throw here.
return;
}
RichTextBox textBox = tabControl.SelectedTab.Controls[0] as RichTextBox;
if (textBox == null)
{
// Could throw here.
return;
}
textBox.Paste();
}
Usage:
myTabControl.PasteIntoCurrentTab();
I suggest you keep some "current state" variables updated so you always have a pointer to the selected Tab Page, and its child control (in the case of a tabbed-notepad emulation discussed here : a TextBox). My preference would be to keep track of the TabPage<>TextBox connections using a Dictionary to avoid having to cast the TextBoxes if they are accessed using the TabPage.Controls route : the following code assumes you have a TabControl named 'tabControl1 on a Form :
Dictionary<TabPage, TextBox> dct_TabPageToTextBox;
int tabCnt = 1;
TabPage currentTabPage;
TextBox currentTextBox;
So, as you create each new TabPage at run-time you call something like this :
private void AddNewTabPage()
{
if (dct_TabPageToTextBox == null) dct_TabPageToTextBox = new Dictionary<TabPage, TextBox>();
currentTabPage = new TabPage("Page " + tabCnt.ToString());
tabControl1.TabPages.Add(currentTabPage);
currentTextBox = new TextBox();
dct_TabPageToTextBox.Add(currentTabPage, currentTextBox);
currentTabPage.Controls.Add(currentTextBox);
currentTextBox.Dock = DockStyle.Fill;
currentTextBox.Text = "sample text for page " + tabCnt.ToString();
tabControl1.SelectedTab = currentTabPage;
tabCnt++;
}
As the end-user changes the selected TabPage you can simply update your current state variables like this :
private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
{
currentTabPage = tabControl1.SelectedTab;
currentTextBox = dct_TabPageToTextBox[currentTabPage];
MessageBox.Show("text in current Tab Page is : " + currentTextBox.Text);
}
So now have the code that is invoked by your menu choices applied only to the currentTextBox.
best, Bill
I tried this for fun ... I made a form with a ToolStripContainer, and a ToolStrip inside it, with the standard buttons (which includes the paste button). I renamed the paste button to pasteButton, and hooking everything up you get:
public Form2()
{
InitializeComponent();
TabControl tc = new TabControl();
toolStripContainer1.ContentPanel.Controls.Add(tc);
tc.Dock = DockStyle.Fill;
TextBox selectedTextBox = null;
pasteButton.Click += (_, __) => selectedTextBox.Paste(Clipboard.GetText(TextDataFormat.Text));
int pages = 0;
newTabButton.Click += (_,__) => {
TextBox tb = new TextBox { Multiline = true, Dock = DockStyle.Fill, ScrollBars = ScrollBars.Vertical };
TabPage tp = new TabPage("Page " + (++pages).ToString());
tc.Selected += (o, e) => selectedTextBox = e.TabPage == tp ? tb: selectedTextBox;
tp.Controls.Add(tb);
tc.TabPages.Add(tp);
tc.SelectedTab = tp;
selectedTextBox = tb;
};
}
what i want to do is actually more complex than this.
but the principal is this..
i want to insert another control like text box into an existing form, but after some event like a click of a button.
the new text box would be inserted into the same form( main form)
what i have got is. i created as usual windows form application, and then put a button there.
then in the same project i add new form window. and put a text box there.
and in the event of button click, i put
form2.showdialog();
it works but it shows as a dialog box.
but what i want is that the text box shows up on the main form, not in the new form as a dialog box.
thank for the asap reply.
If you need only a single text box sometimes visible, sometimes not, I suggest just to add it in the designer and toggle the TextBox.Visible property in the event.
If you need to dynamically add several controls, I suggest to use the TableLayoutPanel and add controls to it at runtime.
Finally you could just add the control to the main form with something like the following.
Control textBox = new TextBox();
// Set the location, size, and all the other properties.
this.Controls.Add(textBox);
This way you have the largest freedom to build your form, but accept for very simple cases it is non-trivial to get a reasonable layout.
private void button1_Click( object sender, EventArgs e )
{
TextBoxt text = new TextBox( );
// set location and other properties
this.Controls.Add( text );
}
hei.
i am able to solve it by using list (generic list)
in main form, create a private variabel List
and create public method to get the variable.
in main form, create a public method to add by looping through the list.
so in the new class i have created, in one of the method i
put the creation of the form. and into here i pass the listcontrol.
and then put all the control variable into the list control.
and on a click of a button, i call the class method, and then it will automatically draw the form controls that created by the class.
private List<Control> listControl;
public windowForm()
{
InitializeComponent();
listControl = new List<Control>();
}
public List<Control> ListControl {
get { return listControl; }
}
public void addControl() {
if (this.listControl.Count() > 0) {
foreach (Control c in listControl)
{
Console.WriteLine("adding "+c.Name);
this.panel1.Controls.Add(c);
}
}
}
public void removeControl() {
if (this.listControl.Count() > 0)
{
foreach (Control c in listControl)
{
Console.WriteLine("removing " + c.Name);
this.panel1.Controls.Remove(c);
}
}
}
and for the new class i have created, i put
this.groupbox_VectorAddition = new System.Windows.Forms.GroupBox();
this.txtBox_v1a = new System.Windows.Forms.TextBox();
this.txtBox_v1b = new System.Windows.Forms.TextBox();
this.txtBox_v1c = new System.Windows.Forms.TextBox();
this.txtBox_v2c = new System.Windows.Forms.TextBox();
this.txtBox_v2b = new System.Windows.Forms.TextBox();
this.txtBox_v2a = new System.Windows.Forms.TextBox();
this.lbl_Vector1 = new System.Windows.Forms.Label();
this.lbl_Vector2 = new System.Windows.Forms.Label();
this.btn_countAddVector = new System.Windows.Forms.Button();
this.btn_resetVector = new System.Windows.Forms.Button();
//put everything into the panel
form.ListControl.Add(btn_resetVector);
form.ListControl.Add(btn_countAddVector);
form.ListControl.Add(lbl_Vector2);
form.ListControl.Add(lbl_Vector1);
form.ListControl.Add(txtBox_v2a);
form.ListControl.Add(txtBox_v2b);
form.ListControl.Add(txtBox_v2c);
form.ListControl.Add(txtBox_v1c);
form.ListControl.Add(txtBox_v1b);
form.ListControl.Add(txtBox_v1a);
form.ListControl.Add(groupbox_VectorAddition);