I have a form containing a tab control, which itself contains five tab pages. These tab pages contain lists, textboxes, and other controls that I update when the user enters the relevant page.
One of the tab pages contains a textbox which I fill with information from an external text file. This information is a 'log' of changes made to documents sorted chronologically so that the most recent change is found at the bottom of the log. When the user enters this tab page, the textbox is filled with information from the external text file (it does this every time to keep the log the user sees up-to-date) and I would then like to scroll to the bottom of the textbox. The code I use to do this works and is:
Dim sr As StreamReader = My.Computer.FileSystem.OpenTextFileReader(My.Settings.logFilePath) ChangeLogBox.Text = sr.ReadToEnd() sr.Close() ChangeLogBox.SelectionStart = ChangeLogBox.Text.Length ChangeLogBox.ScrollToCaret()
The problem I'm having is that the textbox, now revealed as ChangeLogBox, won't scroll to the bottom when this code is contained within the TabPage.Enter event handler. However, it WILL scroll to the bottom if the code is contained within the TabControl.SelectedIndexChanged event handler. It also scrolls to the bottom if the code is run from a button control on the tab page.
I imagine the problem is something to do with the fact that I'm attempting to use methods associated with the ChangeLogBox object before the control has properly loaded on the form. In which case, is there a way to determine whether or not the control has loaded and will respond to the ScrollToCaret() request?
I've also tried the GotFocus, Validated, and LostFocus event handlers and none of them solve the problem. In fact, these events don't even seem to fire when the tab page is selected (weirdly). I only seem to have this issue when scrolling to the caret. I'm able to successfully update other controls on this tab page and others via the Enter event handler.
The entire event handler is:
Private Sub ChangelogPage_Enter() Handles ChangelogPage.Enter Dim initialised As Boolean = False If My.Settings.enableAutoRefresh Then If Not changelogListRefreshed Then While Not initialised Try ChangelogListUpdate() LoadLog() initialised = True NetworkTimeout.Stop() Catch ex As IOException ' Start time-out timer If Not NetworkTimeout.Enabled Then NetworkTimeout.Start() End If End Try End While End If End If ChangelogRefreshButton.Visible = True DescriptionTip.SetToolTip(ChangelogRefreshButton, _ "REFRESH Changelog") FoundLogBox.Text = Nothing ' Force redraw of tabpage so that colours display ChangelogList.Refresh() End Sub
enableAutoRefresh is a setting that is True in this case, so may as well be ignored. changelogListRefreshed is a variable used to stop this update when the user leaves the tab page (again, weirdly, the Enter event seems to fire when the tab page is left as well as entered) and is False upon entering the tab page and True when leaving. The Try... Catch block is used just in case the text file being read from is inaccessible (temporarily).
The LoadLog() method is:
Friend Sub LoadLog() Dim initialised As Boolean = False While Not initialised Try Dim sr As StreamReader = _ My.Computer.FileSystem.OpenTextFileReader( _ My.Settings.logFilePath) ChangeLogBox.Text = sr.ReadToEnd() sr.Close() ChangeLogBox.SelectionStart = ChangeLogBox.Text.Length ChangeLogBox.ScrollToCaret() initialised = True NetworkTimeout.Stop() Catch ex As IOException ' Start time-out timer If Not NetworkTimeout.Enabled Then NetworkTimeout.Start() End If End Try End While End Sub
I've been struggling with this for a while and would appreciate any pointers or ideas!