我想根据用户的选择显示或隐藏选项卡。如果用户选择了男性,则应在名为“男性”的选项卡页面上显示男性表单,如果用户选择了女性,则应在下一个选项卡“女性”中显示类似的下一个表单。
我尝试使用以下代码:
tabControl1.TabPages.Remove(...)
并且tabControl1.TabPages.Add(...)
它添加和删除选项卡页,但这样做会丢失我在选项卡页上的控件...我无法再看到它们。这里问题出在哪里?
我想根据用户的选择显示或隐藏选项卡。如果用户选择了男性,则应在名为“男性”的选项卡页面上显示男性表单,如果用户选择了女性,则应在下一个选项卡“女性”中显示类似的下一个表单。
我尝试使用以下代码:
tabControl1.TabPages.Remove(...)
并且tabControl1.TabPages.Add(...)
它添加和删除选项卡页,但这样做会丢失我在选项卡页上的控件...我无法再看到它们。这里问题出在哪里?
我认为答案要简单得多。
要隐藏选项卡,您可以使用您已经尝试过的方法或直接针对TabPage本身进行操作。
TabControl1.TabPages.Remove(TabPage1) 'Could be male
TabControl1.TabPages.Remove(TabPage2) 'Could be female
a.s.o.
移除选项卡页并不会销毁它和其上的控件。
要再次显示相应的选项卡,只需使用以下代码:
TabControl1.TabPages.Insert(0, TabPage1) 'Show male
TabControl1.TabPages.Insert(1, TabPage2) 'Show female
您可以从TabControl.TabPages集合中删除选项卡页,然后将其存储在列表中。例如:
private List<TabPage> hiddenPages = new List<TabPage>();
private void EnablePage(TabPage page, bool enable) {
if (enable) {
tabControl1.TabPages.Add(page);
hiddenPages.Remove(page);
}
else {
tabControl1.TabPages.Remove(page);
hiddenPages.Add(page);
}
}
protected override void OnFormClosed(FormClosedEventArgs e) {
foreach (var page in hiddenPages) page.Dispose();
base.OnFormClosed(e);
}
在Hans Passant的好解决方案的基础上,我决定编写一个扩展方法,并添加其他东西。令人惊讶的是,即使在.NET 4中,这种基本功能仍未被修复。
public static class TabPageExtensions
{
private struct TabPageData
{
internal int Index;
internal TabControl Parent;
internal TabPage Page;
internal TabPageData(int index, TabControl parent, TabPage page)
{
Index = index;
Parent = parent;
Page = page;
}
internal static string GetKey(TabControl tabCtrl, TabPage tabPage)
{
string key = "";
if (tabCtrl != null && tabPage != null)
{
key = String.Format("{0}:{1}", tabCtrl.Name, tabPage.Name);
}
return key;
}
}
private static Dictionary<string, TabPageData> hiddenPages = new Dictionary<string, TabPageData>();
public static void SetVisible(this TabPage page, TabControl parent)
{
if (parent != null && !parent.IsDisposed)
{
TabPageData tpinfo;
string key = TabPageData.GetKey(parent, page);
if (hiddenPages.ContainsKey(key))
{
tpinfo = hiddenPages[key];
if (tpinfo.Index < parent.TabPages.Count)
parent.TabPages.Insert(tpinfo.Index, tpinfo.Page); // add the page in the same position it had
else
parent.TabPages.Add(tpinfo.Page);
hiddenPages.Remove(key);
}
}
}
public static void SetInvisible(this TabPage page)
{
if (IsVisible(page))
{
TabControl tabCtrl = (TabControl)page.Parent;
TabPageData tpinfo;
tpinfo = new TabPageData(tabCtrl.TabPages.IndexOf(page), tabCtrl, page);
tabCtrl.TabPages.Remove(page);
hiddenPages.Add(TabPageData.GetKey(tabCtrl, page), tpinfo);
}
}
public static bool IsVisible(this TabPage page)
{
return page != null && page.Parent != null; // when Parent is null the tab page does not belong to any container
}
public static void CleanUpHiddenPages(this TabPage page)
{
foreach (TabPageData info in hiddenPages.Values)
{
if (info.Parent != null && info.Parent.Equals((TabControl)page.Parent))
info.Page.Dispose();
}
}
}
我倾向于使用扁平化的外观样式: https://dev59.com/q3RB5IYBdhLWcg3wr44U#25192153
tabControl1.Appearance = TabAppearance.FlatButtons;
tabControl1.ItemSize = new Size(0, 1);
tabControl1.SizeMode = TabSizeMode.Fixed;
但是每个选项卡都显示一个像素,因此如果您删除每个选项卡的所有文本,则选项卡在运行时完全不可见。
foreach (TabPage tab in tabControl1.TabPages)
{
tab.Text = "";
}
之后我使用了一个树形视图,通过点击节点来切换选项卡页面。
另一种方法是使用两个选项卡控件,一个可见,一个不可见。您可以像这样将选项卡从一个控件移动到另一个控件(vb.net):
If Me.chkShowTab1.Checked = True Then
Me.tabsShown.TabPages.Add(Me.tabsHidden.TabPages("Tab1"))
Me.tabsHidden.TabPages.RemoveByKey("Tab1")
Else
Me.tabsHidden.TabPages.Add(Me.tabsShown.TabPages("Tab1"))
Me.tabsShown.TabPages.RemoveByKey("Tab1")
End If
如果标签顺序很重要,就需要在tabsShown的.Add方法上改成.Insert,并指定序号位置。一种实现方式是调用一个返回所需序号位置的程序。
您可以随时隐藏或显示选项卡页面。
'in VB
myTabControl.TabPages(9).Hide() 'to hide the tabpage that has index 9
myTabControl.TabPages(9).Show() 'to show the tabpage that has index 9
public static Action<Func<TabPage, bool>> GetTabHider(this TabControl container) {
if (container == null) throw new ArgumentNullException("container");
var orderedCache = new List<TabPage>();
var orderedEnumerator = container.TabPages.GetEnumerator();
while (orderedEnumerator.MoveNext()) {
var current = orderedEnumerator.Current as TabPage;
if (current != null) {
orderedCache.Add(current);
}
}
return (Func<TabPage, bool> where) => {
if (where == null) throw new ArgumentNullException("where");
container.TabPages.Clear();
foreach (TabPage page in orderedCache) {
if (where(page)) {
container.TabPages.Add(page);
}
}
};
}
使用方法如下:
var showOnly = this.TabContainer1.GetTabHider();
showOnly((tab) => tab.Text != "tabPage1");
通过保留对匿名函数实例的引用,可以保留原始排序。
有人将C#答案合并到这个答案中,所以我不得不在这里发布我的答案。我不喜欢其他解决方案,所以我制作了一个帮助类,可以更轻松地隐藏/显示选项卡,同时保留选项卡的顺序。
/// <summary>
/// Memorizes the order of tabs upon creation to make hiding / showing tabs more
/// straightforward. Instead of interacting with the TabCollection, use this class
/// instead.
/// </summary>
public class TabPageHelper
{
private List<TabPage> _allTabs;
private TabControl.TabPageCollection _tabCollection;
public Dictionary<string, int> TabOrder { get; private set; }
public TabPageHelper( TabControl.TabPageCollection tabCollection )
{
_allTabs = new List<TabPage>();
TabOrder = new Dictionary<string, int>();
foreach ( TabPage tab in tabCollection )
{
_allTabs.Add( tab );
}
_tabCollection = tabCollection;
foreach ( int index in Enumerable.Range( 0, tabCollection.Count ) )
{
var tab = tabCollection[index];
TabOrder[tab.Name] = index;
}
}
public void ShowTabPage( string tabText )
{
TabPage page = _allTabs
.Where( t => string.Equals( t.Text, tabText, StringComparison.CurrentCultureIgnoreCase ) )
.First();
int tabPageOrder = TabOrder[page.Name];
if ( !_tabCollection.Contains( page ) )
{
_tabCollection.Insert( tabPageOrder, page );
}
}
public void HideTabPage( string tabText )
{
TabPage page = _allTabs
.Where( t => string.Equals( t.Text, tabText, StringComparison.CurrentCultureIgnoreCase ) )
.First();
int tabPageOrder = TabOrder[page.Name];
if ( _tabCollection.Contains( page ) )
{
_tabCollection.Remove( page );
}
}
}
public Form1()
{
InitializeComponent();
_tabHelper = new TabPageHelper( tabControl1.TabPages );
}
所有的选项卡页面应该在应用程序加载时存在(即在设计视图中),因为类会记住隐藏/显示选项卡页面的顺序。您可以像这样有选择地在整个应用程序中隐藏或显示它们:
_tabHelper.HideTabPage("Settings");
_tabHelper.ShowTabPage("Schedule");
添加和删除选项卡可能会有点不太有效
也许这会有所帮助
隐藏/显示选项卡页面 => 让tabControl1的tabPage1
tapPage1.Parent = null; //to hide tabPage1 from tabControl1
tabPage1.Parent = tabControl1; //to show the tabPage1 in tabControl1
我的示例代码已经可以工作,但我想通过引用列表中的选项卡来使其更好一些:
Public Class Form1
Dim State1 As Integer = 1
Dim AllTabs As List(Of TabPage) = New List(Of TabPage)
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Check1(State1)
State1 = CInt(IIf(State1 = 1, 0, 1))
End Sub
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
AllTabs.Add(TabControl1.TabPages("TabPage1"))
AllTabs.Add(TabControl1.TabPages("TabPage2"))
End Sub
Sub Check1(ByVal No As Integer)
If TabControl1.TabPages.ContainsKey("TabPage1") Then
TabControl1.TabPages.Remove(TabControl1.TabPages("TabPage1"))
End If
If TabControl1.TabPages.ContainsKey("TabPage2") Then
TabControl1.TabPages.Remove(TabControl1.TabPages("TabPage2"))
End If
TabControl1.TabPages.Add(AllTabs(No))
End Sub
End Class