Скрытие и отображение вкладок в VB .NET - TabManager

Я пытаюсь динамически скрывать и показывать вкладки во время выполнения. Для этого я преобразовал код Эмиля отсюда в vb.net, и в результате проблема в том, что вкладки больше не могут быть показаны после того, как они были скрыты. По крайней мере, если бы они были установлены как невидимые где-то еще, чем где я пытаюсь сделать их видимыми.

редактировать:

После долгого обсуждения я наконец-то получил рабочий результат. я исправил процедуры вызова, и теперь этот код работает. Он может скрывать и отображать вкладки, которые находятся в любой форме, как и в оригинальной версии. Спасибо перейти к пользователю varocarbas..

Скрытие вкладки:

clsTabManager.SetInvisible(tabPage)

Отображение вкладки (звонок из любого класса / формы):

clsTabManager.SetVisible(FormWithTabControl.tabPage, FormWithTabControl.TabControl)

Отображение вкладки (вызов из формы, в которой находится TabControl):

clsTabManager.SetVisible(tabPage, TabControl)

clsTabmanager:

Public Class clsTabManager

    Private Structure TabPageData
        Friend Index As Integer
        Friend Parent As TabControl
        Friend Page As TabPage

        Friend Sub New(index__1 As Integer, parent__2 As TabControl, page__3 As TabPage)
            Index = index__1
            Parent = parent__2
            Page = page__3
        End Sub

        Friend Shared Function GetKey(tabCtrl As TabControl, tabPage As TabPage) As String
            Dim key As String = ""
            If tabCtrl IsNot Nothing AndAlso tabPage IsNot Nothing Then
                key = [String].Format("{0}:{1}", tabCtrl.Name, tabPage.Name)
            End If
            Return key
        End Function
    End Structure

    Private hiddenPages As New Dictionary(Of String, TabPageData)()


    Public Sub SetVisible(page As TabPage, parent As TabControl)
        If parent IsNot Nothing AndAlso Not parent.IsDisposed Then
            Dim tpinfo As TabPageData
            Dim key As String = TabPageData.GetKey(parent, page)

            If hiddenPages.ContainsKey(key) Then
                tpinfo = hiddenPages(key)

                If tpinfo.Index < parent.TabPages.Count Then
                    parent.TabPages.Insert(tpinfo.Index, tpinfo.Page)
                Else
                    ' add the page in the same position it had
                    parent.TabPages.Add(tpinfo.Page)
                End If

                hiddenPages.Remove(key)
            End If
        End If
    End Sub

    Public Sub SetInvisible(page As TabPage)
        If IsVisible(page) Then
            Dim tabCtrl As TabControl = DirectCast(page.Parent, TabControl)
            Dim tpinfo As TabPageData
            tpinfo = New TabPageData(tabCtrl.TabPages.IndexOf(page), tabCtrl, page)
            tabCtrl.TabPages.Remove(page)
            hiddenPages.Add(TabPageData.GetKey(tabCtrl, page), tpinfo)
        End If
    End Sub

    Public Function IsVisible(page As TabPage) As Boolean
        Return page IsNot Nothing AndAlso page.Parent IsNot Nothing
        ' when Parent is null the tab page does not belong to any container
    End Function

    Public Sub CleanUpHiddenPage(page As TabPage)
        For Each info As TabPageData In hiddenPages.Values
            If info.Parent IsNot Nothing AndAlso info.Parent.Equals(DirectCast(page.Parent, TabControl)) Then
                info.Page.Dispose()
            End If
        Next
    End Sub

    Public Sub CleanUpAllHiddenPages()
        For Each info As TabPageData In hiddenPages.Values
            info.Page.Dispose()
        Next
    End Sub

End Class

3 ответа

Решение

Преобразование исходного кода C#, которое вы сделали, не является идеальным (вы должны понимать, что делает каждая часть, вместо того, чтобы копировать по крупицам). в SetVisible/SetInvisible Отчасти это проблема:

Public Shared Function SetInvisible(page As TabPage, frm As Form) 'As Boolean
    page = frm.Controls(page.Name)

    If IsVisible(page) Then
        Dim tabCtrl As TabControl = DirectCast(page.Parent, TabControl)
        Dim tpinfo As TabPageData

        tpinfo = New TabPageData(tabCtrl.TabPages.IndexOf(page), tabCtrl, page)

        tabCtrl.TabPages.Remove(page)
        hiddenPages.Add(TabPageData.GetKey(tabCtrl, page), tpinfo)
    End If
End Function

(это должно быть Sub а не Function) Вы добавляете немного не присутствует в исходном коде: page = frm.Controls(page.Name); Я думаю, что это адаптация, чтобы заставить код работать в ваших конкретных условиях (вы добавили в форму TabPage один, а не один внутри TabControlчто такое нормальное поведение). Это было бы хорошо, но вы не адаптируете функцию SetVisible к этой реальности:

Public Shared Sub SetVisible(page As TabPage, parent As TabControl)
    If parent IsNot Nothing AndAlso Not parent.IsDisposed Then
        Dim tpinfo As TabPageData
        Dim key As String = TabPageData.GetKey(parent, page)

        If hiddenPages.ContainsKey(key) Then
            tpinfo = hiddenPages(key)

            If tpinfo.Index < parent.TabPages.Count Then
                parent.TabPages.Insert(tpinfo.Index, tpinfo.Page)
            Else
                ' add the page in the same position it had
                parent.TabPages.Add(tpinfo.Page)
            End If

            hiddenPages.Remove(key)
        Else
            PrintAllKeys()
        End If
    End If
End Sub

Понять, что делают обе функции: первая (измененная вами) ожидает, что TabPage будет добавлен в форму напрямую (т.е. без родительского TabControl); второй (как в исходном коде C#) ожидает TabPage с родительским TabControl, но ваш ввод этого не имеет. Откуда я это знаю? Если ваш TabPage будет иметь TabControl в качестве родителя, page = frm.Controls(page.Name) было бы Nothing,

Если вы хотите использовать этот код, вы должны предоставить ожидаемые входные данные, то есть TabPages внутри TabControl. В противном случае вы должны изменить его соответствующим образом (не только одну часть, все части). Простой тест для вас, чтобы понять, что требуется:

1- Откройте новый проект и добавьте новый TabControl через "Design View".
2- Скопируйте свой класс, но пусть SetInvisible как в оригинальной версии (удалить page = frm.Controls(page.Name)).
3- Проверьте ваш класс с основной формой и убедитесь, что он работает нормально. Пример кода (это имена по умолчанию при добавлении нового TabControl):

Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load   
    Dim test As clsTabManager = New clsTabManager()

    test.SetInvisible(TabPage1, Me)

    test.SetVisible(TabPage1, TabControl1)
End Sub

Я только что реализовал предложенный вами код и обнаружил проблему. Он сосредотачивается вокруг попыток сделать ранее невидимую закладку снова видимой. Проблема заключается в том, что после того, как вкладка становится невидимой, она больше не является частью элемента управления вкладкой. Он хранится внутри одного из TabpageData структуры, так что это может быть позже получено. Но для того, чтобы сделать вкладку снова видимой, мне пришлось изменить SetVisible() способ включить PageName а не вкладка, а также GetKey() функция для передачи в tabcontrol и имя вкладки.

Вот новый GetKey():

Friend Shared Function GetKey ( tabCtrl As TabControl, tabName As string ) As String
    Dim key As String = ""

    If tabCtrl IsNot Nothing  Then
        key = [String].Format( "{0}:{1}", tabCtrl.Name, tabName )
    End If
    Return key
End Function

А вот и новый SetVisible:

Public Sub SetVisible ( PageName As String, parent As TabControl )
    If parent IsNot Nothing AndAlso Not parent.IsDisposed Then
        Dim tpinfo As TabPageData
        Dim key    As String = TabPageData.GetKey ( parent, PageName )

        If hiddenPages.ContainsKey(key) Then
            tpinfo = hiddenPages(key)

            If tpinfo.Index < parent.TabPages.Count Then
                parent.TabPages.Insert(tpinfo.Index, tpinfo.Page)
            Else
                ' add the page in the same position it had
                parent.TabPages.Add(tpinfo.Page)
            End If

            hiddenPages.Remove(key)
        End If
    End If
End Sub

Вам нужно проверить, есть ли постбэк или нет в вашем frmMain_Load, чтобы он не всегда был невидимым.

Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load

If Not Page.IsPostBack Then
    clsTabManager.SetInvisible(tcManaging.TabPages("tpEdit"))
End If

End Sub
Другие вопросы по тегам