1,105,380 Community Members

How to write to instance of a TextBox from shared function

Member Avatar
Ancient Dragon
Achieved Level 70
27,637 posts since Aug 2005
Reputation Points: 5,232 [?]
Q&As Helped to Solve: 3,037 [?]
Skill Endorsements: 115 [?]
Team Colleague
Featured
Sponsor
 
2
 

I'm trying to write a simple program that detects when files are changed in a folder (for another question here). It has a standard Windows with a TextBox and a couple buttons. Upon program start it calls .NET function FileSystemWatcher then sets up four event handlers for it. What I want is for the event handlers to write something to the TextBox, but VB.NET complains that shared functions can't access instance objects. I know a work-around in c++ by setting a global pointer to the instance which can be accessed by shared functions but can't think of a work around in VB. Anyone know how to do this?

The error is on line 30 of the code posted below.

Private Sub TurnOn()
        watcher = New FileSystemWatcher()
        ' Create a new FileSystemWatcher and set its properties. 
        watcher.Path = txtFolder.Text
        ' Watch for changes in LastAccess and LastWrite times, and 
        ' the renaming of files or directories. 
        watcher.NotifyFilter = (NotifyFilters.LastAccess Or NotifyFilters.LastWrite Or NotifyFilters.FileName Or NotifyFilters.DirectoryName)
        ' watch all files.
        watcher.Filter = "*.*"

        ' Add event handlers. 
        AddHandler watcher.Changed, AddressOf OnChanged
        AddHandler watcher.Created, AddressOf OnChanged
        AddHandler watcher.Deleted, AddressOf OnChanged
        AddHandler watcher.Renamed, AddressOf OnRenamed

        ' Begin watching.
        watcher.EnableRaisingEvents = True

        ' Wait for the user to quit the program.
        'Console.WriteLine("Press 'q' to quit the sample.")
        'While Chr(Console.Read()) <> "q"c
        'End While
        'Return True
        btnOnOff.Text = "OFF"
    End Sub

    Private Shared Sub OnChanged(source As Object, e As FileSystemEventArgs)
        ' Specify what is done when a file is changed, created, or deleted.
        txtFolder.Text = txtFolder.Text + "File: " & e.FullPath & " " & e.ChangeType '<<<< error on this line
    End Sub

The error message is
error BC30369: Cannot refer to an instance member of a class from within a shared method or shared member initializer without an explicit instance of the class.

Member Avatar
Reverend Jim
Noli mentula
5,444 posts since Aug 2010
Reputation Points: 746 [?]
Q&As Helped to Solve: 653 [?]
Skill Endorsements: 51 [?]
Moderator
Featured
 
1
 

If you check out my code snippet BackgroundWorker IP Monitor it shows how to use Delegates to access the textbox from another thread. I think that is what you will have to do.

Member Avatar
TnTinMN
Practically a Master Poster
640 posts since Jun 2012
Reputation Points: 418 [?]
Q&As Helped to Solve: 152 [?]
Skill Endorsements: 16 [?]
 
1
 

Other than the obvious, drop the "Shared" keyword, you can use any of the reference syntaxes to the form shown below.

Jim is correct that you will bump into cross thread issues with the FileSystemWatcher events, so I include an example of that technique as well.

Public Class Form1

   'create a delegate template for the method
   Delegate Sub dummy(ByVal caller As TextBox, ByVal text As String)

   ' a method that matches the template defined above
   Sub settext(ByVal caller As TextBox, ByVal text As String)
      caller.Text = text
   End Sub

   Private Shared Sub test()
      My.Forms.Form1.TextBox1.Text = "wilma"
      CType(My.Application.OpenForms.Item("Form1"), Form1).TextBox1.Text = "barney"

      ' Since you are handling events, these events my arrive on a thread other than the UI thread.
      ' To prevent a cross thread error, check if an Invoke is needed
      If Form1.TextBox1.InvokeRequired Then
         ' invoke a call on the UI thread
         Form1.TextBox1.Invoke(New dummy(AddressOf Form1.settext), New Object() {Form1.TextBox1, "dino"})
      Else
         Form1.TextBox1.Text = "fred"
      End If
   End Sub

End Class

Edit: The reference methods shown above assume that you have the "Application Framework" enabled.

Member Avatar
__avd
Posting Genius (adatapost)
6,703 posts since Oct 2008
Reputation Points: 1,811 [?]
Q&As Helped to Solve: 1,272 [?]
Skill Endorsements: 61 [?]
Moderator
 
0
 

In VB.NET, we can use className (i.e. name of Form class - eg Form1.Text) to access the instance members from within the static methods or other forms/classes. And we use Me keyword if we want to use members of FORM from within the instance methods of current form.

So the we can access controls and their properties via:

form1.TextBox1.Text="Hello" 

However, you can't use this methods (above mentioned) to access/change the controls properties outside the UI thread(into the handlers). You need to call Control.Invoke or Control.BeginInvoke method so that way you can update UI from secondary thread.

So I'd like to suggest two solutions:

Workaround First : Make that handler non-static (non-shared)

Private Sub OnChanged(source As Object, e As FileSystemEventArgs)
        TextBox1.Invoke(Sub()
                            TextBox1.AppendText(e.FullPath & vbCrLf)
                        End Sub)
End Sub

Workaround second : For static event handler, declare shared form reference variable,

Shared frm As Form1
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    TurnOn()
    frm = Me
End Sub
Private Shared Sub OnChanged(source As Object, e As FileSystemEventArgs)
    frm.TextBox1.Invoke(Sub()
                            frm.TextBox1.AppendText(e.FullPath & vbCrLf)
                        End Sub)
End Sub
Member Avatar
Reverend Jim
Noli mentula
5,444 posts since Aug 2010
Reputation Points: 746 [?]
Q&As Helped to Solve: 653 [?]
Skill Endorsements: 51 [?]
Moderator
Featured
 
0
 

In VB.Net (with explicit type) the syntax would be

Dim reftext As TextBox = Me.Controls("TextBox1")
You
This article has been dead for over three months: Start a new discussion instead
Post:
Start New Discussion
Tags Related to this Article