【问题标题】:Change Label.Text from Main Form从主窗体更改 Label.Text
【发布时间】:2014-11-16 01:37:47
【问题描述】:

我在从主窗体编辑窗体中的标签控件的 .text 属性时遇到了一些问题。

这是我想要完成的:

  1. 用户点击开始
  2. 打开另一个带有进度条的窗口
  3. 当主窗体中的程序运行时,标签文本和进度会随着应用程序所在的位置和完成的百分比而更新(完成的百分比只是一个 .Value 和我放入的数字)

    公共类 frmMain 暗淡的进度作为 frmProgress

    公共子 LoadProgress() 初始化组件() 进度 = 新的 frmProgress 进度.显示() 结束子

然后我以我想要的形式调用对象

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

这……在技术上是可行的。但是,它似乎破坏了我所有主要表单变量和对象(如文本框)的可用性。例如,我有一个例外,如果您将其中一个文本框留空,那么在加载进度条表单后它看不到文本框值,因此认为它是空白并引发错误。

如果我删除 InitiliazeComponent() 调用,我仍然可以更改进度条的 .Value,这确实一直有效,我之前能够使用 frmProgress.progTaskProgress.Value = 25 并且它会工作。

抱歉跑题了,如果我删除初始化,我仍然可以访问进度条没有问题,但我的标签的文本值不再改变,应用程序的其余部分运行没有问题。

现在,如果我刚刚启动应用程序,我可能会在主窗体上运行任务并将它们移动到进度条窗体,但是这是对已经接近完成的应用程序的附加/增强,因此它将是在这一点上这样做很麻烦。

或者,我可以只使用 .visible 并根据需要在主窗体上隐藏/显示进度条,但我宁愿将其作为自己的窗体。

我比较啰嗦,所以总结一下: - 上面的代码“有效”,但我无法访问主要表单对象的内容(如文本框中的文本 - 如果我删除 InitializeComponent(),我仍然可以更改进度条对象,并且运行代码仍然可以访问所有其他主窗体对象,但是更改进度窗体上的 .text 值的能力消失了。

我希望我正确地解释了这一点,以便您能够理解我要做什么。


更新: 我发现尝试了一些你发布的解决方案,实际上我的一些陈述确实有效,但我从来没有让他们走得那么远。

        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

我强调了失败和有效的行,尽管网站上的灰色可能有点难以看到。

这一切都在一个 TRY 语句中,对另一个表单上的标签文本的更改在嵌套在 TRY 语句中的 IF 语句中失败,但在 TRY 本身中的行上没有。我希望这是有道理的?

我要好好睡一觉,希望今晚我能变得更有意义。

【问题讨论】:

  • 我不太明白,但这是在后台工作人员中工作吗?如果不是,我建议它可能应该是。 UI 的任何更新都发生在后台工作人员更新进度更改事件中,并且您在后台工作人员的 DoWork 方法中报告进度。这就是我会根据你的问题措辞来做的方式
  • InitializeComponent() 不需要在那里。它调用frmMain 的设计器代码。如果您重新启动 frmProgress - 您也不需要或不想重新启动该表单。您最好使用Update 之类的过程,在其中推送文本和值并让表单管理自己的控件
  • 这是 WPF 还是 WinForm?标记它。 WPF中没有Form。
  • 这是一个 Windows 窗体。我添加了标签。我要睡觉了,因为我是一名夜班工作者,我会再试一试,但是我确实想注意我在下面提到的内容,即使用我的原始方法适用于嵌套 IF 语句之外的行.
  • “失败”是什么意思? “脱离 IF”是什么意思?它会引发异常还是根本不更新控件?请记住,当您将线程置于睡眠状态时,什么都不会发生,因此进度表单可能会更新,但不会重新绘制 UI。 是您的新 UpdateDisplay 方法可以做的事情类型:刷新它更新的控件。

标签: .net vb.net winforms


【解决方案1】:

深入InitializeComponent 过程,您会看到它正在初始化主窗体上的所有控件。这只需要在构造函数中完成一次。

您更新进度表的方法陷入实施细节。实际上,需要更新进度的任何形式、模块或类的每个过程都必须在该形式的控件中根植,按名称设置它们。

您可以定义您想要做什么作为更新进度显示,并将详细信息(如何)留给拥有/容纳控件。这是通过添加一个方法并调用它来完成的:

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

现在任何表单、模块、类或过程都可以告诉表单实例更新并将详细信息留给表单:

frmProgress.UpdateDisplay("sometext", 25)

这种抽象的价值在于,如果你改变一些东西,比如添加一个红-黄-绿进度颜色指示器,你只需要在一个地方更改代码。

【讨论】:

  • 很遗憾,这个没有用。但是,我确实注意到 IF 语句中的最后几行确实改变了文本。因此,即使使用我创建的 Public Sub,嵌套在 IF 语句中也有一些明显不喜欢的地方。
  • 您的代码/帖子/问题没有提及嵌套的 IF - 听起来像是在发挥作用。试试这个方法的简单测试 - 它会起作用。
【解决方案2】:

尝试使用反射。您可以使用下面的函数(SetControlProperty)从您的应用程序中的任何其他表单更改任何表单上的任何控件的任何属性。

这是一个例子(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

【讨论】:

    猜你喜欢
    • 2019-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-19
    • 1970-01-01
    • 1970-01-01
    • 2011-07-23
    • 1970-01-01
    相关资源
    最近更新 更多