vb.net tabpage

Hi Experts

I have a tabcontrol with 2 tabpages on the 2nd tab page I have a listview when there is information in the list view I would
Like the 2nd tabpage text (Heading) color to change from black to red / bold to visually tell the user to go o the 2nd tabpage

You help will be appreciated
KevinfeeningAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Karrtik IyerSoftware ArchitectCommented:
Do you want to change the font color of the tab 2 header when user clicks on Tab 2? Is my understanding correct?
And you want this in Visual Basic .NET?

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
KevinfeeningAuthor Commented:
no to prompt the user to go to tab 2

Using Microsoft visual studio 8 and vb.net
Karrtik IyerSoftware ArchitectCommented:
And you have a listview object on tab2 , so whenever data is changed in that list view, and if user is not on tab2 (means he is on tab1), then change the tab header of tab 2 to red color, is this correct?
Your Guide to Achieving IT Business Success

The IT Service Excellence Tool Kit has best practices to keep your clients happy and business booming. Inside, you’ll find everything you need to increase client satisfaction and retention, become more competitive, and increase your overall success.

Karrtik IyerSoftware ArchitectCommented:
Please check if the below works for you, I have a windows form in VB.NET with 2 tabs, in the 2nd tab there is a listview. And when I launch the app, the selected tab is the 1st tab by default. I have a timer in my form to simulate incoming data on tab 2, after 3 seconds, the timer elapsed is called, and I add the items to list view, and then call TabControl refresh to refresh the header.
To draw the color of tab header in different color, in form load I have to set the Drawmode of tab to OwnerDrawFixed and handle the draw item event of tab control. In this draw item event I check if current tab is 1st tab and if new items have got added in 2nd tab then I draw second header text in Red color. See screenshots below. Also attached is the code below.
TabHeader_Before.pngTabHeader_After.png
Public Class Form1
    Private _listviewtimer As New System.Timers.Timer(3000)
    Private _changetabheadercolor As Boolean = False
  
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        TabControl1.DrawMode = DrawMode.OwnerDrawFixed
        _listviewtimer.Enabled = True
        _listviewtimer.AutoReset = True
        AddHandler _listviewtimer.Elapsed, AddressOf TimerElapsed
    End Sub
    Private Sub TimerElapsed(ByVal sender As Object, e As Timers.ElapsedEventArgs)
        If Me.ListView1.InvokeRequired Then
            Me.Invoke(Sub() ListView1.Items.Add("ABC"))
            Me.Invoke(Sub() ListView1.Items.Add("DEF"))
            Me.Invoke(Sub() ListView1.Items.Add("GHI"))
            _changetabheadercolor = True
            Me.Invoke(Sub() TabControl1.Refresh())
            _listviewtimer.Stop()
        End If
    End Sub

    Private Sub TabControl1_DrawItem(sender As Object, e As DrawItemEventArgs) Handles TabControl1.DrawItem

        'Get the first tab and draw it normally
        Dim firstTab As TabPage = TabControl1.TabPages(0)

        'Get the area of the header of this TabPage
        Dim HeaderRect1 As Rectangle = TabControl1.GetTabRect(0)

        '  Create two Brushes to paint the Text
        Dim BlackTextBrush As New SolidBrush(Color.Black)
        Dim RedTextBrush As New SolidBrush(Color.Red)

        'Set the Alignment of the Text
        Dim sf As New StringFormat()
        sf.Alignment = StringAlignment.Center
        sf.LineAlignment = StringAlignment.Center
        e.Graphics.DrawString(firstTab.Text, e.Font, BlackTextBrush, HeaderRect1, sf)

        Dim secondtab As TabPage = TabControl1.TabPages(1)

        Dim HeaderRect2 As Rectangle = TabControl1.GetTabRect(1)
        '  Paint the Text using the appropriate Bold and Color setting 
        If _changetabheadercolor And TabControl1.SelectedIndex = 0 Then
            Dim BoldFont As New Font(TabControl1.Font.Name, TabControl1.Font.Size, FontStyle.Bold)
            e.Graphics.DrawString(secondtab.Text, BoldFont, RedTextBrush, HeaderRect2, sf)

        Else
            e.Graphics.DrawString(secondtab.Text, e.Font, BlackTextBrush, HeaderRect2, sf)
        End If

        '  Job done - dispose of the Brushes
        BlackTextBrush.Dispose()
        RedTextBrush.Dispose()
        
    End Sub
End Class

Open in new window

Karrtik IyerSoftware ArchitectCommented:
i assume you have a way to figure out that list view on tab 2 has changed, in the above example after adding the data to list view, I explicitly call TabControl.Refresh. Ideally, it would have been good if we have an event to handle in list view which has item added or removed item. To get events for item added or removed we will have to specialize the list view and write our own class, so that we get these events.
You can look at the below article which explains how this works.
http://www.codeproject.com/Articles/4406/An-Observer-Pattern-and-an-Extended-ListView-Event
KevinfeeningAuthor Commented:
thanks good code I do have a way to check the list view or if you used a label that changed do you need all the code to just change the color as you showed in the examples tabpage1 / myheader
Karrtik IyerSoftware ArchitectCommented:
To change the tab header color the main code is in draw item event and setting property of tab as owner draw fixed in form load. Other things like timer in my code is not needed if you have a way to find out of list view was modified. In draw item I have a boolean flag set to find if list view had been modified that you will have to Set it in your case at appropriate place.
KevinfeeningAuthor Commented:
Hi in the code I check mCommentRichText.Text has a value and set warning to true I want to then run the Private Sub TabControl1_DrawItem event to change the color but the Me.Invoke(Sub() TabControl1.Refresh())  the word sub gives error - expression expected
The user on the first Tab scrolls through a table and the data may have a comment or not if it does I want  the 2nd tab to go red as in your display to prompt the user to go to the second tab


 mCommentRichText.Text = reader1.GetString(9)

                            If mCommentRichText.Text IsNot "" Then
                                warning = True
                            Else
                                warning = False
                            End If

                           Me.Invoke(Sub() TabControl1.Refresh())

Open in new window

Karrtik IyerSoftware ArchitectCommented:
Hi Kevin which is the version of .NET framework you are using?
KevinfeeningAuthor Commented:
Microsoft Visual Studio 2008 Version 9.0.30729.4462 QFE
Microsoft .Net Framework Version 3.5 SP1
Karrtik IyerSoftware ArchitectCommented:
Can you try this instead? I think in VS2008 there is no concept of anonymous lambda which I have used in my code earlier.
'Add the below sub to your class
Private sub myTabRefresh()
TabControl1.Refresh()
End Sub
'Change invoke to call like below
me.Invoke(New MethodInvoker(myTabRefresh))

Open in new window

KevinfeeningAuthor Commented:
Worked if addressof added to invoker (if not added it gives error - methodinvoker requires an addressof expression) it activates the myTabRefresh event but still not activating the  

Private Sub mDockRecordTabControl_DrawItem(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DrawItemEventArgs) Handles mDockRecordTabControl.DrawItem event

If mCommentRichText.Text IsNot "" Then
               warning = True
               Me.Invoke(New MethodInvoker(AddressOf mytabrefresh))
          Else
              warning = False
              Me.Invoke(New MethodInvoker(AddressOf mytabrefresh))
          End If

          Private Sub mytabrefresh()
              TabControl1.Refresh()
         End Sub

          Private Sub TabControl1_DrawItem(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DrawItemEventArgs) Handles mDockRecordTabControl.DrawItem

               Your Code added  here
 
          end sub 

Open in new window

Karrtik IyerSoftware ArchitectCommented:
Have you set the draw mode of your tab control like below on form load?
TabControl1.DrawMode = DrawMode.OwnerDrawFixed
KevinfeeningAuthor Commented:
Had it turned on but must have turned off when trying to get it to work

Thanks for help all works fine
KevinfeeningAuthor Commented:
Excellent support and effort
Karrtik IyerSoftware ArchitectCommented:
You are welcome :)
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic.NET

From novice to tech pro — start learning today.