代码之家  ›  专栏  ›  技术社区  ›  madlan

访问窗体之间的控件

  •  0
  • madlan  · 技术社区  · 14 年前

    我有一个线程在子窗体上运行,我想激活父窗体上的控件,但不能。如果是从子窗体UI线程执行的,它将正常工作:

    (formmain.setControlPropertyValue(formmain.rbsql2005,“选中”,true))。

    但不是从子窗体上运行的线程:

    public class formrestoredb
    private子按钮1_click(byval sender as system.object,byval e as system.eventargs)处理按钮1。单击
    dim t=新线程(addressof updateListView1)
    启动()
    结束子
    
    
    私有子更新列表视图1()
    'formmain.setControlPropertyValue(formmain.rbsql2005,“选中”,true)
    formmain.rbsql2005.checked=真
    结束子
    
    端类
    
    
    公共类窗体主
    
    委托子setControlValueCallback(ByVal OControl作为控件,ByVal PropName作为字符串,ByVal PropValue作为对象)
    
    public子setControlPropertyValue(ByVal OControl作为控件,ByVal PropName作为字符串,ByVal PropValue作为对象)
    如果(ocontrol.invokeRequired),则
    
    将d变暗为新的setControlValueCallback(setControlPropertyValue的地址)
    ocontrol.invoke(d,new object()ocontrol,propName,propValue)
    否则
    dim t as type=ocontrol.[getType]()
    dim props as propertyinfo()=t.getproperties())
    作为道具中的属性信息
    如果p.name.toupper()=propname.toupper(),则
    p.setvalue(ocontrol,propvalue,无)
    结束如果
    接下来
    结束如果
    结束子
    
    端类
    < /代码> 
    
    

    我做错什么了?

    =

    (formmain.setControlPropertyValue(formmain.rbsql2005,“选中”,true))。

    但不是从子窗体上运行的线程:

    Public Class FormRestoreDB
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim t = New Thread(AddressOf UpdateListView1)
        t.Start()
    End Sub
    
    
    Private Sub UpdateListView1()
        'FormMain.SetControlPropertyValue(FormMain.RBSQL2005, "Checked", True)
        FormMain.RBSQL2005.Checked = True
    End Sub
    
    End Class
    
    
    Public Class FormMain
    
    Delegate Sub SetControlValueCallback(ByVal oControl As Control, ByVal propName As String, ByVal propValue As Object)
    
    Public Sub SetControlPropertyValue(ByVal oControl As Control, ByVal propName As String, ByVal propValue As Object)
        If (oControl.InvokeRequired) Then
    
            Dim d As New SetControlValueCallback(AddressOf SetControlPropertyValue)
            oControl.Invoke(d, New Object() {oControl, propName, propValue})
        Else
            Dim t As Type = oControl.[GetType]()
            Dim props As PropertyInfo() = t.GetProperties()
            For Each p As PropertyInfo In props
                If p.Name.ToUpper() = propName.ToUpper() Then
                    p.SetValue(oControl, propValue, Nothing)
                End If
            Next
        End If
    End Sub
    
    End Class
    

    我做错什么了?

    2 回复  |  直到 14 年前
        1
  •  3
  •   Hans Passant    14 年前
     FormMain.SetControlPropertyValue(FormMain.RBSQL2005, "Checked", True)
    

    这是vb.net支持使用 类型 要引用的表单的名称 实例 形式的。这是从vb6继承过来的一个时代错误,使用表单的类型名是正常的。

    当您使用线程时,这会崩溃,因为“formmain”具有线程关联性。换句话说,它有 <ThreadStatic> 属性。当你在工作线程中使用它时,你会得到一个 新的 表单的实例,而不是用户正在查看的实例。此新实例不可见,因为从未调用其show()方法。这就是为什么你看不到你的代码有任何影响的原因。如果在代码中调用show(),则会看到它弹出。然而,它已经死了,线程没有发送消息循环。你应该注意到的另一个影响是invokeRequired是假的,你知道这不可能是对的。

    你必须停止使用formmain。如果这段代码位于该类中,那么您可以简单地使用我。如果没有,则必须使用属性或构造函数参数传递表单引用。Q&D修复程序是使用application.openforms(0)

        2
  •  0
  •   Chris Laplante    14 年前

    您需要使用invoke( http://msdn.microsoft.com/en-us/library/aa334883%28v=VS.71%29.aspx )或开始与父线程交互。