Скрытие и отображение вкладок в tabControl - PullRequest
32 голосов
/ 29 июля 2010

Я пытаюсь показать или скрыть вкладки по выбору пользователя. Если пользователь выбирает пол мужской, то на вкладке «мужчина» должна отображаться форма для мужчины, а если пользователь выбирает женщину, аналогичная следующая форма должна отображаться на следующей вкладке «женщина»

Я пытался использовать

tabControl1.TabPages.Remove(...)

и

tabControl1.TabPages.Add(...)

Он добавляет и удаляет вкладки, но при этом также теряются мои элементы управления на вкладках ... Я не вижу их обратно. в чем здесь проблема?

Ответы [ 18 ]

34 голосов
/ 26 октября 2012

Я думаю, что ответ намного проще.

Чтобы скрыть вкладку, вы можете просто использовать способ, которым вы уже пробовали, или использовать саму вкладку.1007 * Удаление TabPage не разрушает его и элементы управления на нем.Чтобы снова отобразить соответствующую вкладку, просто используйте следующий код

TabControl1.TabPages.Insert(0, TabPage1) 'Show male
TabControl1.TabPages.Insert(1, TabPage2) 'Show female
32 голосов
/ 29 июля 2010

Вы можете удалить вкладку из коллекции 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);
    }
6 голосов
/ 15 декабря 2011

Улучшение хорошего решения Ханса Пассанта Я решил написать метод расширения, основанный на его решении, а также добавить другие вещи.Я удивлен, что даже в .NET 4 эта базовая функциональность не была исправлена.

  • Реализован как метод расширения, который можно использовать более прозрачным образом
  • ЧистыйМетод up только очищает страницы удаляемого / очищаемого элемента управления.
  • По возможности страница вкладки восстанавливается в прежнее положение.Это не всегда возможно, если вы скрываете / отображаете несколько вкладок.
  • Он выполняет некоторую проверку ошибок и параметров
  • Чтобы сделать его невидимым, он обнаруживает своего родителя.При отображении его необходимо указывать, поскольку свойство Parent при удалении вкладки равно нулю.

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();
            }
        }

    }
2 голосов
/ 27 октября 2012

Другой подход будет иметь два элемента управления вкладками, один видимый, а другой нет. Вы можете перемещать вкладки с одной на другую следующим образом (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

Если порядок вкладок важен, измените метод .Add на tabsShown на .Insert и укажите порядковый номер. Один из способов сделать это - вызвать подпрограмму, которая возвращает желаемую порядковую позицию.

1 голос
/ 09 апреля 2016

Я предпочитаю делать плоский стиль: https://stackoverflow.com/a/25192153/5660876

    tabControl1.Appearance = TabAppearance.FlatButtons;
    tabControl1.ItemSize = new Size(0, 1);
    tabControl1.SizeMode = TabSizeMode.Fixed;

Но на каждой вкладке отображается пиксель, поэтому, если вы удалите весь текст каждой вкладки, то вкладкистать невидимым идеально во время выполнения.

    foreach (TabPage tab in tabControl1.TabPages)
    {
        tab.Text = "";
    }

После этого я использую древовидную структуру, чтобы переключаться между вкладками ... нажимая на узлы.

1 голос
/ 29 июля 2010

Мой пример кода работает, но я хочу сделать его несколько лучше, обновляя вкладку из списка:

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
1 голос
/ 14 января 2014

Мне проще очистить все вкладки, добавить желаемые:

PropertyTabControl.TabPages.Clear();
        PropertyTabControl.TabPages.Add(AspectTabPage);
        PropertyTabControl.TabPages.Add(WerkstattTabPage);

или

PropertyTabControl.TabPages.Clear();
        PropertyTabControl.TabPages.Add(TerminTabPage);
1 голос
/ 14 ноября 2012
    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");

Исходный порядок сохраняется путем сохранения ссылки на экземпляр анонимной функции.

0 голосов
/ 25 октября 2017

Если вы можете позволить себе использовать Tag элемент TabPage, вы можете использовать это расширение

    public static void HideByRemoval(this TabPage tp)
    {
        TabControl tc = tp.Parent as TabControl;

        if (tc != null && tc.TabPages.Contains(tp))
        {
            // Store TabControl and Index
            tp.Tag = new Tuple<TabControl, Int32>(tc, tc.TabPages.IndexOf(tp));
            tc.TabPages.Remove(tp);
        }
    }

    public static void ShowByInsertion(this TabPage tp)
    {
        Tuple<TabControl, Int32> tagObj = tp.Tag as Tuple<TabControl, Int32>;

        if (tagObj?.Item1 != null)
        {
            // Restore TabControl and Index
            tagObj.Item1.TabPages.Insert(tagObj.Item2, tp);
        }
    }
0 голосов
/ 31 августа 2017

И, основываясь на ответе Эмиля (и Слагстера), я обнаружил, что немного проще расширить TabControl (вместо TabPages). Таким образом, я могу установить страницы невидимыми или видимыми одним вызовом, а также не беспокоиться о нулевых родительских ссылках для невидимых страниц.

Пример вызова: MyTabControl.SetTabVisibilityExt ("tabTests", isDeveloper);

public static class WinFormExtensions
{
    public static TabPage FindTabByNameExt( this TabControl tc, string tabName)
    {
        foreach (TabPage tab in tc.TabPages)
            if (tab.Name == tabName)
                return tab;

        return null;
    }

    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 tc, TabPage tabPage)
        {
            string key = "";
            if (tc == null || tabPage == null)
                return key;

            key = $"{tc.Name}:{tabPage.Name}";
            return key;
        }
        internal static string GetKey(TabControl tc, string tabName)
        {
            string key = "";
            if (tc == null)
                return key;

            key = $"{tc.Name}:{tabName}";
            return key;
        }
    }

    private static Dictionary<string, TabPageData> hiddenPages = new Dictionary<string, TabPageData>();

    public static void SetTabVisibleExt(this TabControl tc, string tabName)
    {
        if (tc == null || tc.IsDisposed)
            return;

        if (tc.IsTabVisibleExt(tabName))
            return;

        string key = TabPageData.GetKey(tc, tabName);
        if (hiddenPages.ContainsKey(key))
        {
            TabPageData tpinfo = hiddenPages[key];
            if (tpinfo.Index < tc.TabPages.Count)
                tc.TabPages.Insert(tpinfo.Index, tpinfo.Page); // add the page in the same position it had
            else
                tc.TabPages.Add(tpinfo.Page);

            hiddenPages.Remove(key);
            return;
        }
        else
            throw new ApplicationException($"TabControl={tc.Name} does not have Invisible TabPage={tabName}");
    }

    public static void SetTabInvisibleExt(this TabControl tc, string tabName)
    {
        if (tc == null || tc.IsDisposed)
            return;

        if (IsTabInvisibleExt(tc, tabName))
            return;

        TabPage page = tc.FindTabByNameExt(tabName);
        if (page != null)
        {
            string key = TabPageData.GetKey(tc, page);
            TabPageData tpInfo = new TabPageData(tc.TabPages.IndexOf(page), tc, page);
            tc.TabPages.Remove(page);
            hiddenPages.Add(key, tpInfo);
            return;
        }
        else // Could not find the tab, and it isn't already invisible.
            throw new ApplicationException($"TabControl={tc.Name} could not locate TabPage={tabName}");
    }

    // A convenience method to combine the SetTabInvisible and SetTabInvisible.
    public static void SetTabVisibilityExt(this TabControl tc, string tabName, bool? isVisible)
    {
        if (isVisible == null)
            return;

        if (isVisible.Value)
            tc.SetTabVisibleExt(tabName);
        else
            tc.SetTabInvisibleExt(tabName);
    }

    public static bool IsTabVisibleExt(this TabControl tc, string tabName)
    {
        TabPage page = tc.FindTabByNameExt(tabName);
        return page != null;
    }

    public static bool IsTabInvisibleExt(this TabControl tc, string tabName)
    {
        string key = TabPageData.GetKey(tc, tabName);
        return hiddenPages.ContainsKey(key);
    }

    public static void CleanUpHiddenPagesExt(this TabControl tc)
    {
        foreach (TabPageData info in hiddenPages.Values)
        {
            if (info.Parent != null && info.Parent.Equals((TabControl)tc))
                info.Page.Dispose();
        }
    }

}
...