Article Options
Premium Sponsor
Premium Sponsor

 »  Home  »  Windows Development  »  Dynamically Alter a Windows Form Via a User Control and the TabControl in VB.NET and C#
Dynamically Alter a Windows Form Via a User Control and the TabControl in VB.NET and C#
by Monty Nail | Published  06/15/2002 | Windows Development | Rating:
Monty Nail

Monty Nail is a Senior Software Developer for Timeline, Inc. (www.timeline.com) based in Bellevue, Washington. He is responsible for the company's financial reporting product.

Monty is a self-taught programmer with a B.S. in History from Portland State University and has done post-baccalaureate studies in Japanese and TESOL (Teaching English to Speakers of Other Languages).

His first full-time programming job was using VBA to write Excel-based tracking programs for a construction company's cost control department. He has been using Visual Basic since version 4 was released.

 

View all articles by Monty Nail...
Dynamically Alter a Windows Form Via a User Control and the TabControl in VB.NET and C#

Article source code (both VB.NET and C#): dynamictabs.zip

When designing a form, you don't always know what data an individual user will need to see at run-time. Dynamically changing the form using a combination of a User Control and the TabControl is one way to accomplish this task.

In some scenarios, providing a static user interface is sufficient. However, if the number of business objects to display to the user varies, you need an adaptable means of presentation. One way to accomplish this is to programmatically add new tabs and controls to your UI at runtime. In this example, you will add a new instance of a User Control to a TabPage then add the TabPage to the TabControl on a Windows Form.

Getting Started

Create a new blank Visual Studio Solution (File | New | Blank Solution) named "DynamicTabs". To this solution, you will eventually add a Class Library, a Control Library, and a Windows Forms Library. VB.NET is shown here but the steps are similar if using C#. You will find both VB.NET and C# implementations in the article code.

Create a Class Library

Start by adding a new Class Library (File | Add Project | New Project) called "AccountsClassLibrary". Change the default class name, Class1, to be Accounts.

Define a collection of Account objects which in turn contain a collection of CodeListing objects. The Account class is similar in concept to a database table and the CodeListing class to an individual row within a table. The Selection property of the Account class stores what the user selected in the UI.

Public Class Accounts
    Inherits CollectionBase

    Public Sub Add(ByVal Value As Account)
        Me.InnerList.Add(Value)
    End Sub
    
    Default Public ReadOnly Property Item(ByVal Index As IntegerAs Account
        Get
            Return CType(MyBase.InnerList.Item(Index), Account)
        End Get
    End Property

End Class

Public Class Account
    Public CodeListings As New CodeListings()
    Public AccountName As String
    Public Selection As String
End Class

Public Class CodeListings
    Inherits CollectionBase

    Public Sub Add(ByVal CodeValue As Integer_
        ByVal CodeDisplayValue As StringByVal CodeDescription As String)
        Dim objCodeListing As New CodeListing()
        objCodeListing.CodeValue = CodeValue
        objCodeListing.CodeDisplayValue = CodeDisplayValue
        objCodeListing.CodeDescription = CodeDescription
        Me.InnerList.Add(objCodeListing)
    End Sub

End Class

Public Class CodeListing
    Public CodeValue As Integer
    Public CodeDisplayValue As String
    Public CodeDescription As String
End Class
Generated using PrettyCode.Encoder

Create a Windows Control Library

Add a new Windows Control Library project to your solution and name it "AccountsWindowsControlLibrary". Rename the default UserControl1 file to be "UserControlAccounts" and change the Name property of the control to be "usercontrolAccounts". Add a text box and a list view to the form as follows:

PropertyValue
NametextboxSelection
Text(blank)
AnchorTop, Left, Right
PropertyValue
NamelistviewAccountCodes
AnchorTop, Bottom, Left, Right
FullRowSelectTrue
HideSelectionFalse
ViewDetails

Next add a reference to the AccountsClassLibrary project by going to Project | Add Reference. Select the Projects tab on the form that appears. Highlight the AccountsClassLibrary. Click the Select button to add it to selected components, and then click the OK button.

Create an Account property in the user control in such a way that when the property is set the list view control will be populated. Then create a handler for when the user changes the selected item(s).

Private m_Account As AccountsClassLibrary.Account

Public Property Account() As AccountsClassLibrary.Account

    Get
        Return m_Account
    End Get
    
    Set(ByVal Value As AccountsClassLibrary.Account)
        m_Account = Value
        Me.listviewAccountCodes.Clear()
        Dim objCodeColumn As New System.Windows.Forms.ColumnHeader()
        objCodeColumn = Me.listviewAccountCodes.Columns.Add("Code"100_
            HorizontalAlignment.Center)

        Dim objDescriptionColumn As New ColumnHeader()
        objDescriptionColumn = Me.listviewAccountCodes.Columns.Add_
            "Description"100HorizontalAlignment.Left)
        objDescriptionColumn.Width = Me.listviewAccountCodes.Width - _
            objCodeColumn.Width

        '/Add the rows
        Dim objCodeListing As AccountsClassLibrary.CodeListing
        Dim objListViewItem As ListViewItem

        For Each objCodeListing In m_Account.CodeListings
            objListViewItem = New ListViewItem()
            objListViewItem.Text = objCodeListing.CodeDisplayValue
            'Add the item to display in the description column
            objListViewItem.SubItems.Add(objCodeListing.CodeDescription)
            'Use the tag property to maintain a reference to the CodeListing 
            ' object
            objListViewItem.Tag = objCodeListing
            Me.listviewAccountCodes.Items.Add(objListViewItem)
        Next
    End Set

End Property

Private Sub listviewAccountCodes_SelectedIndexChanged_
    ByVal sender As System.Object_
    ByVal e As System.EventArgsHandles _
    listviewAccountCodes.SelectedIndexChanged
    Dim objStringBuilder As New System.Text.StringBuilder()
    Dim i As Integer
    Dim objCodeListing As AccountsClassLibrary.CodeListing

    For i = 0 To listviewAccountCodes.SelectedIndices.Count - 1
    
        If objStringBuilder.Length > 0 Then
            objStringBuilder.Append(", ")
        End If
        
        objCodeListing = New AccountsClassLibrary.CodeListing()
        objCodeListing = CType(listviewAccountCodes.SelectedItems(i).Tag_
            AccountsClassLibrary.CodeListing)
        'Create a text string to store the user selection based on the real 
        ' value, not the display value
        objStringBuilder.Append(objCodeListing.CodeValue.ToString)

    Next
    
    Me.textboxSelection.Text = objStringBuilder.ToString
End Sub
Generated using PrettyCode.Encoder

Now build the solution so the Windows Control Library will be compiled (Build | Build Solution).

Create a Windows Application Project

Add a new Windows Application project to your solution. Name it "DynamicTabsExample". Set this project to be the startup project (Project | Set as StartUp Project). Add references to both the AccountsClassLibrary and the AccountsWindowsControlLibrary.

Rename the default Form1.vb to FormMain.vb, and change the Name property of the form to formMain. Change the Text property of the form to "Dynamic Tabs Example". Add a tab control to the form as follows:

PropertyValue
NametabcontrolAccounts
DockFill

Create the Form Load

Add code to the forms load event to fill the Accounts and CodeListings collections. For each item in the Accounts collection add a new tab with the user control in it.

Private m_Accounts As New AccountsClassLibrary.Accounts()

Private Sub formMain_Load(ByVal sender As Object_
    ByVal e As System.EventArgsHandles MyBase.Load
    Dim objAccount As AccountsClassLibrary.Account

    If m_Accounts.Count = 0 Then
        objAccount = New AccountsClassLibrary.Account()
        objAccount.AccountName = "Table1"
        objAccount.CodeListings.Add(1"001""Descrip 1")
        objAccount.CodeListings.Add(2"002""Descrip 2")
        objAccount.CodeListings.Add(3"003""Descrip 3")
        m_Accounts.Add(objAccount)

        objAccount = New AccountsClassLibrary.Account()
        objAccount.AccountName = "Table2"
        objAccount.CodeListings.Add(10"010""Descrip 10")
        objAccount.CodeListings.Add(20"020""Descrip 20")
        objAccount.CodeListings.Add(30"030""Descrip 30")
        m_Accounts.Add(objAccount)

        objAccount = New AccountsClassLibrary.Account()
        objAccount.AccountName = "Table3"
        objAccount.CodeListings.Add(100"100""Descrip 100")
        objAccount.CodeListings.Add(200"200""Descrip 200")
        objAccount.CodeListings.Add(300"300""Descrip 300")
        m_Accounts.Add(objAccount)
        Me.tabcontrolAccounts.TabPages.Clear()

        For Each objAccount In m_Accounts
            Dim objTabPage As New TabPage(objAccount.AccountName)
            Dim objControl As New _
                AccountsWindowsControlLibrary.usercontrolAccounts()
            objTabPage.Controls.Add(objControl)
            '/Add to control before setting the Account property so internal 
            ' resizing works correctly
            Me.tabcontrolAccounts.TabPages.Add(objTabPage)
            With objControl
                .Dock = DockStyle.Fill
                .Account = objAccount
            End With
        Next

    End If

End Sub
Generated using PrettyCode.Encoder

The last thing to change is to set the renamed form as the startup object. In the Solution Explorer, select the DynamicTabsExample project. From the main menu select Project | Properties. Change the "Startup object" dropdown to formMain and click OK.

Build the solution and you're ready to run the project.

Select items in the list on each tab. You can see that each one is operating independently.

Summary

Using dynamic tabs can enhance the user experience and allows code re-use via a User Control.

Related devCity.NET articles:

How would you rate the quality of this article?
1 2 3 4 5
Poor Excellent
Tell us why you rated this way (optional):

Article Rating
The average rating is: No-one else has rated this article yet.

Article rating:3.50980392156864 out of 5
 51 people have rated this page
Article Score59330
Sponsored Links