65.9K
CodeProject is changing. Read more.
Home

Dynamic Tab Extended Version

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.96/5 (9 votes)

Aug 2, 2022

CPOL

2 min read

viewsIcon

16920

downloadIcon

436

An extended version of the Dynamic Tab article

Introduction

This document and the demo are about an extended version of the 'Dynamic Tab' article.

Background

The CodeProject article "Add/Remove Tabs Dynamically in WPF" was my template for an extended VB.NET version with additional features as requested in the comments to the original article.

New Features

  • Converted to VB.NET
  • New TabItem header styling based on an idea that was posted here
  • Loading a (rich) text file into tab
  • Loading a UserControl into tab
  • Ribbon for menu items

The Ribbon

The Ribbon includes

  • Application Menu
  • QAT (QuickAccessToolbar)
  • Ribbon Tabs Start, Ribbon Settings and Help

Version 1.2 or below: The Ribbon works only for the top level tabcontrol.

With C# version 1.3 the Ribbon works for the top level tabcontrol and for the usercontrol.

With command Open, you can load a plain text file or a rich text file. The Tab will show the file name after doing that.

The commands Search, Print and Info are only dummies without any function.

QAT (QuickAccessToolbar)

You can remove buttons from the QAT (on right click, a context menu appears for that).

And you can show QAT below the Ribbon. You can Restore QAT from Settings Tab as well.

And you can change backcolor of the Ribbon.

Top Level tabcontrol

The basic features were already explained in the original article.

You can add a tabpage with a click on the + button. The tabpage content is a RichTextBox.

Loading a (rich) text file into tab with Ribbon Command Load UC:

   Private Sub Open_Click(sender As Object, e As RoutedEventArgs) Handles Open.Click, 
                                               AppCmdOpenQAT.Click, AppCmdOpen.Click

            Add_TabItem(sender, Nothing)
            tab.Header = io.OpenFileDlg(activeRTBox)

   End Sub

   Public Function OpenFileDlg(ByVal ActiveTBox As Object) As String

        Dim dialog As FileDialog = New OpenFileDialog()

        Try

            dialog.Filter = "All Files(*.*)|*.*|RTF Files (*.rtf)|*.rtf"
            dialog.FilterIndex = 1
            dialog.Title = "RTE - Open File"
            dialog.DefaultExt = "rtf"
            dialog.ShowDialog()

            If dialog.FileName = "" Then Exit Function

            Dim strExt As String
            strExt = System.IO.Path.GetExtension(dialog.FileName)
            strExt = strExt.ToUpper()

            If ActiveTBox.GetType.ToString = "System.Windows.Controls.RichTextBox" Then

                Select Case strExt

                    Case ".RTF"

                        Dim t As New TextRange(ActiveTBox.Document.ContentStart, 
                                               ActiveTBox.Document.ContentEnd)
                        Dim file As New FileStream(dialog.FileName, FileMode.Open)
                        t.Load(file, System.Windows.DataFormats.Rtf)
                        file.Close()

                    Case Else

                        Dim t As New TextRange(ActiveTBox.Document.ContentStart, 
                                               ActiveTBox.Document.ContentEnd)
                        Dim file As New FileStream(dialog.FileName, FileMode.Open)
                        t.Load(file, System.Windows.DataFormats.Text)
                        file.Close()

                End Select

                Dim currentFile As String = dialog.FileName
                dialog.Title = "Editor: " & currentFile.ToString()
                Return dialog.SafeFileName

            Else

                If ActiveTBox.GetType.ToString = "System.Windows.Controls.TextBox" Then

                    Dim currentFile As String = dialog.FileName
                    ActiveTBox.Text = ReadTextLines(dialog.FileName)
                    Return dialog.SafeFileName

                End If

            End If

        Catch ex As Exception

            MessageBox.Show(ex.Message)

        End Try

    End Function

    Public Function ReadTextLines(FileName As String) As String

        Dim fi As New IO.FileInfo(FileName)

        ReadTextLines = Nothing

        Try

            If fi.Length > 0 Then

                ' Open the file using a stream reader.
                Using sr As New StreamReader(FileName)

                    Dim line As String

                    ' Read the stream to a string and write the string to the console.

                    line = sr.ReadToEnd()

                    line = line.Replace(" " & Environment.NewLine, Environment.NewLine)
                    line = line.Replace(" " & Chr(9), "")
                    line = line.Replace(Chr(10), "")
                    line = line.Replace(Chr(13), Environment.NewLine)
                    line = line.Replace(Environment.NewLine & Environment.NewLine & 
                                        Environment.NewLine, Environment.NewLine)
                    line = line.Trim

                    ' http://forums.devx.com/showthread.php?
                             146639-VB-NET-remove-extra-blank-lines-from-file
                    line = line.Replace(Environment.NewLine & Environment.NewLine, 
                                        Environment.NewLine)

                    Return line

                End Using

            Else

                ' MsgBox("FileLength = 0") 

            End If

        Catch ex As Exception

            MessageBox.Show(ex.Message)

        End Try

    End Function

UserControl - Concept and Code

The XAML content which shows the TabItem header styling:

Loading the UC

This happens from the Ribbon with Load UC (in Group View):

        Private Sub LoadUCRibbonButton_Click(sender As Object, e As RoutedEventArgs) 
                                             Handles LoadUCRibbonButton.Click

            Me.tabDynamic.DataContext = Nothing

            Dim tab As TabItem = AddTabItemUC()

            ' bind tab control
            'tabDynamic.DataContext = _tabItems;
            Me.tabDynamic.DataContext = CorrectTabHeaders(_tabItems)

            ' select newly added tab item
            Me.tabDynamic.SelectedItem = tab

            RibbonWPF.IsEnabled = False

        End Sub

        Public Function AddTabItemUC() As TabItem

            Dim count = _tabItems.Count

            ' create new tab item
            tab = New TabItem()

            tab.Background = New SolidColorBrush(Colors.LightGoldenrodYellow)

            tab.Header = String.Format("UserControl1 [Doc. {0}]", count)
            'tab.Name = String.Format("document{0}", count)
            tab.HeaderTemplate = TryCast(Me.tabDynamic.FindResource("TabHeader"), 
                                         DataTemplate)

            AddHandler tab.MouseDoubleClick, 
                       New MouseButtonEventHandler(AddressOf tab_MouseDoubleClick)
            
            AddHandler tab.MouseLeftButtonUp, 
                       New MouseButtonEventHandler(AddressOf tab_MouseDownClick)

            ' add controls to tab item, this case I added just a UserControl
            Dim txt As UserControl1 = New UserControl1
            txt.Name = "txt"
            tab.Content = txt
            tab.Name = txt.Name

            ' insert tab item right before the last (+) tab item
            _tabItems.Insert(count - 1, tab)

            Return tab

        End Function

You can add a tabpage with a click on + button. The tabpage content is a RichTextBox.

Conclusion

This is only a demo – it is not production ready. But I think it will allow you a variety of extensions.

Final Note

I am very interested in feedback of any kind - problems, suggestions and other.

Credits / Reference

History

  • 2nd August, 2022 - Initial submission
  • 4th August, 2022 - Replaced source files with new version 1.1
  • 21st February, 2023 - Replaced source files with new version 1.2 - now with VB and C# versions
  • 31th May, 2024 - With C# version 1.3 the Ribbon works for the top level tabcontrol and for the usercontrol.