Change Label.Text from Main Form

I'm having some trouble with editing the .text property of a label control in a form from the main form.

Here is what I am trying to accomplish:

  1. User clicks start
  2. Another window with the progress bar opens up
  3. As the program in the main form runs I the label text and progress updates with where the application is at and the % completed (the % completed is just a .Value and number I'm placing in)

    Public Class frmMain Dim progress As frmProgress

    Public Sub LoadProgress() InitializeComponent() progress = New frmProgress progress.Show() End Sub

Then I call the objects in the form I want with

progress.label.text = "stuff"
progress.prgTaskProgress.Value = 25

This... technically works. However it seems to break the availability of the all of my main form variables and objects (like text boxes). For example I have an exception for if you leave one of the text boxes blank, well after the progress bar form is loaded it doesn't see the text box value, so thinks its blank and throws an error.

If I remove the InitiliazeComponent() call, I can still change the .Value of the progress bar, which really has always worked I was able to just use frmProgress.progTaskProgress.Value = 25 before and it would work.

Sorry got off topic, if I remove the initialize, I can still access the progress bar no problem, but the text values of my label no longer change and the rest of the application runs with no issues.

Now if I were just starting the application, I would probably have the tasks that run on the main form and move them to the progress bar form, however this is an additional / enhancement to an already nearly completed application so it would be troublesome to do this at this point.

Alternatively, I can just use a .visible and hide/show the progress bar on the main form as needed, but I'd rather have it as its own form.

I tend to ramble so I'll summarize: - The code above "works", but I lose access to the main form objects contents (like the text in a text box - If I remove InitializeComponent() I can still change the progress bar object and the running code can still access all the other main form objects, but the ability to change the .text value on the progress form is gone.

I hope I explained this properly that you can understand what I'm trying to do.


Update: I found trying some of your posted solutions that actually some of my statements DO work, but I never let them get that far before.

        If My.Computer.FileSystem.FileExists(extFilePath + fileXP) Then
            fileXPNew = domainName + " " + fileXP
            My.Computer.FileSystem.RenameFile(extFilePath + fileXP, fileXPNew)
            My.Computer.FileSystem.CopyFile(extFilePath + fileXPNew, modSharePath + fileXPNew, True)
            ' FAIL progress.lblTaskName.Text = "Processing XP Migration Readiness Report"
            Thread.Sleep(15000) ' Pause for OneSync delay
            My.Computer.FileSystem.DeleteFile(extFilePath + fileXPNew)
            progress.prgTaskProgress.Value = 90
        End If

        progress.lblTaskName.Text = "Transfer Complete. Closing Processes please wait..."

        Thread.Sleep(2000)
        progress.prgTaskProgress.Value = 93
        Thread.Sleep(2000)
        progress.prgTaskProgress.Value = 96
        Thread.Sleep(2000)
        progress.prgTaskProgress.Value = 99
        Thread.Sleep(2000)
        progress.prgTaskProgress.Value = 100
        ' WORKS progress.lblTaskName.Text = "Process Complete. Please verify your OneDrive sync. Resetting application..."
        Thread.Sleep(2000)
        progress.Close()
    Catch ex As Exception
        MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
    End Try
Catch ex As Exception
    MessageBox.Show(ex.Message, "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try

I highlighted the lines that fail and work though the gray out on the website might be a little tough to see.

It's all in a TRY statement, the changes to the label text on the other form fail in the IF statements which are nested in a TRY statement, but not on the lines that are in the TRY by itself. I hope that makes sense?

I'm gonna get some sleep and hopefully I'll be able to make more sense tonight.


ANSWERS:


Drill into the InitializeComponent procedure and you will see it is initializing all the controls on the main form. This only needs to be done once from the constructor.

Your method of updating the progress form is bogged down in implementation details. As it is, every procedure in any form, module or class which needs to update the progress is obliged to root around in the controls of that form, by name, to set them.

You can define what you want to do as update the progress display and leave the details (how) to the form which owns/houses the controls. This is done by adding a method and calling it:

Public Class FormProgress

    Public Sub UpdateDisplay(txt as String, v As integer)          '?
       ' the details of which controls are involved 
       ' remain in the form which contains them:

       lblProgress.text = txt
       progBar.Value = v
    End Sub

Now any form, module, class or procedure can tell the form instance to update and leave the details to the form:

frmProgress.UpdateDisplay("sometext", 25)

The value in such abstraction is that if and when you change something such as adding a red-yellow-green progress color indicator, you only need to change the code in one place.


Try using reflection. You can use the function below(SetControlProperty) to change any property of any control on any form from any other form within your application.

Here is an example(form1)

Option Strict On
Option Explicit On
Option Infer Off
Imports System.Reflection
Public Class Form1
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Form2.Show()
    End Sub
    Public Sub SetControlProperty(ControlName As String, propertyName As String, Value As Object)
        Dim obj As Control = Me.Controls(ControlName)
        If obj Is Nothing Then
            MsgBox("Control not found!")
        Else
            Dim prop As PropertyInfo() = obj.GetType.GetProperties
            For Each pi As PropertyInfo In prop
                If pi.Name.ToLower = propertyName.ToLower Then
                    pi.SetValue(obj, Value)
                End If
            Next
        End If
    End Sub
End Class

(Form2)

Option Strict On
Option Explicit On
Option Infer Off
Public Class Form2
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Form1.SetControlProperty("Button1", "Text", "Hello World!")
    End Sub
End Class


 MORE:


 ? What's the difference between these approaches to reference bundled CSS in ASP.NET Web Forms 4.5?
 ? Detect release / debug in gulp using Visual Studio 2015
 ? How to add a default Default.aspx to a ASP.NET Web Application Project?
 ? Using a wwwroot folder (ASP.NET 5 style) in ASP.NET 4.5 project
 ? Ajax call not working with web method
 ? Ajax call not working with web method
 ? Ajax call not working with web method
 ? ASP .NET: Cannot call Page WebMethod using jQuery
 ? Calling a function / database update using Ajax via Jquery
 ? Calling a WebMethod using jQueryAjax "GET"