vb.net - 如何从另一个模块更改表单元素的属性 [英] vb.net - how to change a property of a form element from another module
问题描述
我正在尝试根据公共属性 (LogQry) 的设置过程更改按钮 (cmdLogQry) 的背景颜色 - 根据该属性的新值.
I am trying to change the background color of a button (cmdLogQry) from a Set-procedure of a public property (LogQry) - according to the new value of the property.
如果属性在属于包含按钮的表单的代码中被更改(在相同甚至另一个按钮的 Click 方法中),它就会起作用.但是,如果正在从另一个模块更改属性(COM 端口 DataReceived 事件的处理程序过程),则它不起作用.没有错误消息或任何东西 - LogQry 的值改变了,但按钮的颜色没有改变.
It works if the property is being changed in the code belongig to the form containing the button (in the Click method of the same or even another button). But it does not work if the property is being changed from another module (handler procedure for COM ports DataReceived event). No error message or anything - the LogQry gets its value changed all right, but the color of the button does not change.
我做错了什么?
Public Class Handler
Private _logQry As Boolean = False
Public Property LogQry() As Boolean
Get
Return _logQry
End Get
Set(ByVal value As Boolean)
_logQry = value
If value Then
frmMain.cmdLogQry.BackColor = Color.Red
Else
frmMain.cmdLogQry.BackColor = Color.Blue
End If
End Set
End Property
Private Sub comPort_DataReceived(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs)
...
LogQry = Not LogQry ' does NOT change color
...
End Sub
End Class
Public Class frmMain
Private comm As New Handler()
...
Private Sub cmdLogQry_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdLogQry.Click
comm.LogQry = Not comm.LogQry ' does change color
End Sub
...
End Class
推荐答案
这个问题是由 VB.NET 实现创建的表单类的默认实例引起的.更多关于默认实例可以在这里找到和来自 Hans Passant 的回答.
本质上,当您定义一个表单类时,VB.NET 编译器会创建该类的默认实例,该类的名称与该类的名称相同,但这在 NET 等面向对象的环境中会产生很多误解.
This problem is caused by the default instance of the form class created by the VB.NET implementation. More on default instances could be found here and in this answer from Hans Passant.
Essentially when you define a form class, VB.NET compiler creates a default instance of that class named with the same name of the class, but this creates a lot of misunderstanding in an object oriented environment like NET.
要解决您的问题,您需要在接收 frmMain 实际实例的 Handler 类中实现一个构造函数,将其存储在类变量中,并在您想修改实际显示表单上的某些内容时使用该实例
To fix your problem you need to implement a constructor in your Handler class that receives the actual instance of frmMain, store it inside a class variable and use that instance when you want to modify something on the actual displayed form
Public Class Handler
Private _logQry As Boolean = False
Private _mainInstance As frmMain
Public Sub New(mainInstance as frmMain)
_mainInstance = mainInstance
End Sub
Public Property LogQry() As Boolean
Get
Return _logQry
End Get
Set(ByVal value As Boolean)
_logQry = value
If value Then
_mainInstance.cmdLogQry.BackColor = Color.Red
Else
_mainInstance.cmdLogQry.BackColor = Color.Blue
End If
End Set
End Property
....
End Class
现在,当您创建 Handler 实例时,将引用传递给当前的 frmMain
Now, when you create the Handler instance pass the reference to the current frmMain
Public Class frmMain
Private comm As Handler
...
Private Sub cmdLogQry_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdLogQry.Click
comm = new Handler(Me)
comm.LogQry = Not comm.LogQry ' does change color
End Sub
...
End Class
请记住,此解决方案也会产生问题.它将类 Handler 与您的 frmMain 耦合在一起,现在两者不可分割.可能更好的方法是在 Handler 类中创建一个事件,这样每个想要收到通知的表单都可以订阅该事件并在需要时接收信息.
Keep in mind that this solution creates also problems. It couples the class Handler to your frmMain and the two are now inseparable. Probably a better approach is to create an Event in the Handler class so, every form that wants to be notified could subscribe to the event and receieves the information when needed.
这篇关于vb.net - 如何从另一个模块更改表单元素的属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!