K Feening
asked on
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
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
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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?
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.
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.
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
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
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
ASKER
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
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.
ASKER
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
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())
Hi Kevin which is the version of .NET framework you are using?
ASKER
Microsoft Visual Studio 2008 Version 9.0.30729.4462 QFE
Microsoft .Net Framework Version 3.5 SP1
Microsoft .Net Framework Version 3.5 SP1
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))
ASKER
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_Draw Item(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DrawI temEventAr gs) Handles mDockRecordTabControl.Draw Item event
Private Sub mDockRecordTabControl_Draw
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
Have you set the draw mode of your tab control like below on form load?
TabControl1.DrawMode = DrawMode.OwnerDrawFixed
TabControl1.DrawMode = DrawMode.OwnerDrawFixed
ASKER
Had it turned on but must have turned off when trying to get it to work
Thanks for help all works fine
Thanks for help all works fine
ASKER
Excellent support and effort
You are welcome :)
ASKER
Using Microsoft visual studio 8 and vb.net