In c# how can I destroy a tab on a tab control by targeting it's name? I've a tab named "Hello!" and I'd like to close it programatically. There's no guarantee that it will be the selected tab at the time.
The TabControl class provides a TabPages property that returns a TabPageCollection containing all of the TabPages in the control.
So you can use the Item property to retrieve the TabPage with the specified name.
For example, if the tab page you want is named "Hello!", you would write:
var tabPage = myTabControl.TabPages["Hello!"];
To remove the TabPage from the control, use the RemoveByKey method:
myTabControl.TabPages.RemoveByKey("Hello!");
Of course, in order for this to work, you'll need to make sure that you've set the keys of your TabPages to match the caption text they display.
You can try something like this:
for (int i = tabControl1.TabPages.Count - 1; i >= 0; i--) {
if (tabControl1.TabPages[i].Text == "Hello!")
tabControl1.TabPages[i].Dispose();
}
I'm assuming you meant the "Text" of the TabPage, since "Hello!" wouldn't be a valid name for a control.
Note: this code will dispose of any TabPage that says "Hello!"
Related
Edit:
This is not a duplicate of Icons in TabControl C# - How?. The question there is about adding icons to tab pages. Here it is about how the change the error provider error icon position to be inside the header instead of to the right of the tab page itself. Also, the error provider error icon has the functionality that when you hover the mouse on it, you see the error text, which you do not see if you simply add an icon to the header.
I have a form with a TabControl. The form has also an ErrorProvider. When I try to use the following code:
errorProvider1.SetError(tabPage1, "error");
The error icon is shown to the right of the tab page, and it is cut-off by the tab control itself:
I would like the icon to be shown next to the tab page header. Something like this (made with Photoshop):
I do not know where to start, or how to approach this.
Edit:
I have a class responsible for adding errors to a control, and showing them using an error provider. This class is used for TextBoxes, NumericUpDowns etc. I would like to use it also for TabPages. The problem is that when I use it for tab pages I get the result shown above. The trick of adding an error icon to the header using an ImageList and then add a tooltip is not good, because it is specific to tab pages, and I cannot implement it in my class which is general to all controls. So I really need to change the settings of the tab page so when I use errorProvider.SetError(...) it is shown in the header.
ErrorProvider shows error icon of the TabPage in tab page's client area.
By playing with IconAlignment or IconPadding, you can show error icon of TabControl on one of the tab pages' headers, but it's error icon for the whole TabControl.
In a real application each of the tab pages can contain controls which are not valid and you may want to show the validation icon on tab pages not for the tab control.
My suggestion is using tab page icon by setting ImageList containing the error icon as image list of the TabControl and by setting ImageIndex of the TabPage, show or hide the image icon. This way you can show the error icon for every tab page which needs it:
Example
To setup the example, follow these steps:
Create a Form.
Drop a TabControl, an ErrorProvider and an ImageList on the Form.
Set ImageList property of tabControl1 to imageList1.
Drop two TextBox on tabPage1.
I assume, just for example, you are going to validate these two text box controls using Validating event. The key point is here. When you validate any control, check if it's hosted in a TabPage, check validity of all children of TabPage and set the error icon based on that:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
this.AutoValidate = AutoValidate.EnableAllowFocusChange;
imageList1.ColorDepth = ColorDepth.Depth32Bit;
imageList1.Images.Add(errorProvider1.Icon);
tabControl1.ImageList = imageList1;
textBox1.Validating += textBox_Validating;
textBox2.Validating += textBox_Validating;
}
private void textBox_Validating(object sender, CancelEventArgs e)
{
var textBox = (TextBox)sender;
if (string.IsNullOrEmpty(textBox.Text))
{
this.errorProvider1.SetError(textBox, "Value is required.");
e.Cancel = true;
}
else
this.errorProvider1.SetError(textBox, null);
var tabPage = textBox.Parent as TabPage;
if (tabPage != null)
ValidateTabPage(tabPage);
}
void ValidateTabPage(TabPage tabPage)
{
var tabIsValid = tabPage.Controls.Cast<Control>()
.All(x => string.IsNullOrEmpty(errorProvider1.GetError(x)));
if (tabIsValid)
tabPage.ImageIndex = -1;
else
tabPage.ImageIndex = 0;
}
You can do the following.
Rectangle rc = tabControl1.GetTabRect(0); // Replace with the index of Tab required
errorProvider1.SetIconPadding(tabControl1, -rc.Left-20);;
errorProvider1.SetError(tabControl1, "Error String");
You also need to set
errorProvider1.SetIconAlignment(tabControl1, ErrorIconAlignment.TopLeft);
Sample (With Second Tab Selected - based on comments),
You would need to prepend whitespace to your TabPage Text to ensure there is sufficient space for showing the icon
With Icon on Second Tab
I'm attempting to get the TextEditor control off of the currently selected tab in my tab control. The tabs and text editors are created dynamically so simply referencing the text editor isn't an option. I've searched far and wide and so far, no answer has helped me.
The following code works for Winforms, but not WPF:
var currentTextEdit = tabControl.SelectedTab.Controls.OfType<TextEditor>().First();
Is there something along these lines that perhaps I'm missing?
This is how I'm creating each tab and adding a TextEditor control to each tab created:
TabControl itemsTab = (TabControl)this.FindName("tabControl");
TextEditor textEdit = new TextEditor();
Then to create the new tab and add the text editor:
TabItem newTab = new TabItem();
newTab.Content = textEdit;
itemsTab.Items.Add(newTab);
Further down in the code I get the currently selected tab like so:
TabItem ti = tabControl.SelectedItems as TabItem;
And using the GetChildOfType extension method, I'm attempting to get the current text editor like so:
var currentTextEditor = ti.GetChildOfType<TextEditor>();
This code returns the NullReferenceException:
File.WriteAllText(saveF.FileName, currentTextEditor.Text);
Indeed I wrote a not right thing in my comment. TabControl works in a little different way in comparing with other controls. It has a collection of TabItems. TabControl can show every header of each TabItem which belongs to its collection.
At the same time TabControl "grabs" the selected TabItem's content and add it to its ContentPresenter (it is called PART_SelectedContentHost - just use ILSpy).
So, returning to your issue, you have to search for your TextEditor directly in the TabControl. Then you can use this code:
TabControl itemsTab = (TabControl)FindName("tabControl");
TextEditor currentTextEditor = itemsTab.GetChildOfType<TextEditor>();
if (currentTextEditor != null)
{
File.WriteAllText(saveF.FileName, currentTextEditor.Text);
}
You should always check if the object you obtain from GetChildOfType<T> method is not null, since if GetChildOfType<T> cannot find a control whose type is T, it returns null.
As I told in my previous comment you can find here the code of GetChildOfType<T>.
I hope this answer can help you.
When working with WPF I usually use the method
var currentTextEdit = tabControl.SelectedTab.Children.OfType<TextEditor>().First();
i'm using telerik control.
So i want to ask,
In winforms application ,Is it possible to add more than one panel in same location and display one at a time just like show/hide property.
Make sure you have placed all panel control in same container or form. then you can use Visible property to show and hide panel. BringFront and SendToBack function will be used to bring panel on top or send it to back. If you have placed any panel in another panel then that will be disappeared when you Hide parent panel. So, Make sure all panels' parent control must be same. To determine the parent control simply select that panel and press escape key to select their parent.
private void LoadPanels()
{
panel1.Location = new Point(10,10);
panel2.Location = new Point(10,10);
panel3.Location = new Point(10,10);
panel4.Location = new Point(10,10);
panel5.Location = new Point(10,10);
VisiblePanel("panel1");
}
private void VisiblePanel(string panelName)
{
string[] panels = new string[]{"panel1","panel2","panel3","panel4","panel5"};
for (int i=0;i<panels.Length;i++)
this.Controls[panels[i]].Visible = (panels[i] == panelName);
this.Controls[panelName].BringToFront(); //Not required you can remove this line.
}
Here's a slightly different approach you might want to consider...
Are you wanting to be able to programmatically select the contents of a rectangular area at runtime, selecting among various controls to display? If so, you could use a custom TabControl which has its tabs (not the pages) hidden.
Then you can select which page is displayed by programmatically changing its SelectedIndex property at runtime.
Doing it like this means that your form editor will show a normal tab control, which allows you to much more easily add the content to each page - but at runtime the tabs will be hidden from the user; they will just see the contents of the currently selected page.
See Hans Passant's answer here for how to create such a custom tab control.
(However, you might also want to override the OnKeyDown for the custom tab control in order to ignore Ctrl-Tab.)
This is stupid and I did it before, but now its not working and I cant find a solution online. I have a form and one tab page. on the tab page there are 4 tabs. how can I make the 4th tab selected when the form loads? I also want to use the tab's text, or name, and not the tab index.
Just select the tab in your form constructor. The boilerplate code is:
public Form1() {
InitializeComponent();
tabControl1.SelectedTab = tabPage4;
// or:
tabControl1.SelectedIndex = 3;
}
You need to loop through the tabs to find the one you want, then set the TabControl's SelectedTab property.
How do I programmatically reorder the tabs in a TabControl? I need to sort the tabs depending on some conditions.
If it's possible to do the reordering through the designer, i guess we must be able to do it through code at runtime too.
Create a new Form.
Create a new TabControl.
Notice it has two TabPage controls, and TabPage1 is the first tab.
In form's Load event, add
this.TabControl1.TabPages.Remove(this.TabPage2)
this.TabControl1.TabPages.Insert(0, this.TabPage2)
Run the form.
Notice TabPage2 is now the first tab.
Note that if you fail to remove the tab page, it will still show at its old location. In other words, you will have two tabs of the same tab page.
You have to redefine your tab page collection, in order to change the index of your tab pages.
The following lines of code can also do the trick, this kind of solution also works for other kind of data that has no direct way of sorting:
- convert to a list
- sort the list
- put it back
public static void Sort(TabControl tabControl)
{
var tabList = tabControl.TabPages.Cast<TabPage>().ToList();
tabList.Sort(new TabPageComparer());
tabControl.TabPages.Clear();
tabControl.TabPages.AddRange(tabList.ToArray());
}
public class TabPageComparer : IComparer<TabPage>
{
public int Compare(TabPage x, TabPage y)
{
return string.Compare(x.Text, y.Text);
}
}
thelost is right. Below is a quick sample code.
I have a tab control with 2 tabs (tabpage1, tabpag2)
Then I declare two tabpages and store the existing tabs in the tabcontrol in it.
abPage tbp1 = new TabPage();
TabPage tbp2 = new TabPage();
tbp1 = tabControl1.TabPages[0];
tbp2 = tabControl1.TabPages[1];
Then on a button click I removed the tabs using
tabControl1.TabPages.Remove(tabControl1.TabPages[0]);
Now if you want to change the order then you will have top add it to the tab in that order
//Order changed
tabControl1.TabPages.Add(tbp2);
tabControl1.TabPages.Add(tbp1);
Note: This is untested quick code.
Go inside Designer.cs file
There you will find
/// [Your TabControl Name]
yourTabControl.Controls.Add(yourPage1);
yourTabControl.Controls.Add(yourPage2);
yourTabControl.Controls.Add(yourPage3);
The adding order is your tabpages' order in the tabcontrol. Change the order how you wish. Remove and Add functions of TabControl.Controls will help you as Shoban answered.
try this after Initilizacomponent(). this code will give you freedom to change it programmatically in .cs file.
this.tabReceive.Controls.Remove(this.metroTabPage4);
this.tabReceive.Controls.Remove(this.metroTabPage5);
this.tabReceive.Controls.Add(this.metroTabPage4);
this.tabReceive.Controls.Add(this.metroTabPage5);
Sometimes I have tabControls with several tabPages. At runtime tabPages are made invisible (by removing them) an added later again.
After this the tabPages may be in wrong order. I use this code to redorder them again:
public void ReorderTabPages()
{
// Demo code to reorder tabControl with tabPages
// where some tabPages may be unwanted at the moment
// caution: events like "SelectedIndexChanged" does fire!
// List of wanted tab pages
List<TabPage> wantedTabPages = new List<TabPage>();
// remember the current selected tab
TabPage currentTabPage = this.tabControl.SelectedTab;
// check if all possibly active tabs are currently visible
// check it in the order they should be displayed
// after that they are in the correct order in "wantedTabPages"
if (this.tabControl.TabPages.IndexOf(this.tabPage_01) >= 0)
wantedTabPages.Add(this.tabPage_01);
if (this.tabControl.TabPages.IndexOf(this.tabPage_02) >= 0)
wantedTabPages.Add(this.tabPage_02);
if (this.tabControl.TabPages.IndexOf(this.tabPage_03) >= 0)
wantedTabPages.Add(this.tabPage_03);
if (this.tabControl.TabPages.IndexOf(this.tabPage_04) >= 0)
wantedTabPages.Add(this.tabPage_04);
this.tabControl.SuspendLayout();
// remove all currently visible tab pages
for (int i = this.tabControl.TabPages.Count - 1; i >= 0; i--)
this.tabControl.TabPages.RemoveAt(i);
// add the tabPages in the correct order
foreach (var wantedPage in wantedTabPages)
this.tabControl.TabPages.Add(wantedPage);
// restore the currently selected tabPage
this.tabControl.SelectedTab = currentTabPage;
this.tabControl.ResumeLayout();
}