2010-06-30 91 views
17

考虑一个带有几个单选按钮和一个复选框的简单.NET表单。如何防止在.NET中进行表单初始化时触发值更改事件?

每个单选按钮都有一个CheckedChanged处理程序设置,该设置根据复选框的状态执行某些操作。

我的问题是,当我初始化默认的单选按钮被检查(从设计器属性窗口)CheckedChanged事件触发该单选按钮,但复选框尚未初始化,所以我要么null指针异常或在处理程序中使用了错误的值。无论哪种方式,我不希望该处理程序代码运行,除非用户在窗体加载后选择一个单选按钮。

我目前通过不初始化单选按钮来解决这个问题,但是我最终需要设置该默认值,最好的地方是来自设计者。我还可以添加一个boolean字段,该字段在表单完全加载之前不会设置为true,如果该值为false则不处理事件,但这是一种肮脏的黑客行为。

我该怎么做才能防止处理程序运行其代码?

+0

这是一个明确的Visual Studio错误,在我看来。设置一个初始化标志(如x77的答案)是最简单的解决方法,但它应该由编译器负责。 – xpda 2010-06-30 20:03:19

+0

这是一个已知的* bug /特性*。当您使用VS中的内置升级工具将VB6项目升级到VB.NET时,它实际上会在这些事件中插入UPGRADE_WARNING注释。 (''UPGRADE_WARNING:事件TextBox1.TextChanged可能会在表单初始化时触发.') – awe 2010-07-28 07:44:00

+0

对于后人,MSDN文章中有关如何处理@ awe的评论中引用的警告:https://msdn.microsoft.com/zh-cn/ us/library/26aab97z%28v = vs.71%29.aspx:set ** IsInitializing **“to ** true **在窗体的构造函数中,在** InitializeComponent **调用之前;将其设置为** false **紧接电话后。“ – 2016-01-13 00:34:10

回答

16

“我也可以放置一个布尔型的字段,它在表单完全加载之前不会设置为true,如果这是错误的,则不处理事件,但这是一种肮脏的黑客攻击。”

这也是最简单和最好的方式!

可以这么说,.NET提供了一种简洁的方式来打开和关闭所有事件处理程序,直到窗体被加载。即使只是你正在处理的。它仍然不够灵活,禁用你想要启用但禁用你没有。通常,表单设置会发生,并且您希望事件触发。此外,如果没有事件触发,表单将无法正确建立。

+9

仍然觉得脏:) – CodeFusionMobile 2010-06-30 15:48:54

+19

我写了这个答案后,我不得不洗澡。 – FastAl 2010-06-30 16:34:35

3

简单的解决方法是声明初始化变量:

Private Initializing as boolean = True 

    Private Sub rb_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles rbNuevos.CheckedChanged, RbDesaparecidos.CheckedChanged, RbModificados.CheckedChanged, RbNoDesap.CheckedChanged, RbDesHoy.CheckedChanged, RbChT.CheckedChanged 
     if Initializing then return 

     'Your Code  
    End Sub 

    Public Sub New() 

     ' Llamada necesaria para el Diseñador de Windows Forms. 
     InitializeComponent()  
     ' Agregue cualquier inicialización después de la llamada a InitializeComponent(). 

     initializing = false 
    end sub 

最复杂的:从方法中删除“手柄”,并在新的方法使用AddHandler

Public Sub New() 

     ' Llamada necesaria para el Diseñador de Windows Forms. 
     InitializeComponent()  
     ' Agregue cualquier inicialización después de la llamada a InitializeComponent(). 

     AddHandler RbChT.CheckedChanged, AddressOf rb_CheckedChanged 
    end sub 
+0

要添加新的方法:写:“Sub New”并按回车 – x77 2010-06-30 16:07:15

23

为了让它感觉略少脏,如果在窗体的构造函数初始化该控件,你可能能够使用形式IsHandleCreated属性,而不是你自己的布尔检查,如果它实际上应该验证或不。
我会认为,通常情况下,你不想在第一次显示它之前验证任何东西,并且直到它没有创建句柄。

代码示例:

Private Sub myRadioButton_CheckedChanged(sender As Object, e As EventArgs) Handles myRadioButton.CheckedChanged 
If myRadioButton.Checked AndAlso myRadioButton.IsHandleCreated Then 
    'Do Work 
End If 
End Sub 
+1

是的,这是不太脏,它的工作原理!我遇到了同样的问题,并在事件中检查“IsHandleCreated”形式解决了所有问题! – awe 2010-07-29 08:20:07

+1

这应该是答案。 – Sire 2014-12-22 14:24:47

0

有一件事我发现,工作原理是将事件加载表格后手动。

为此,您可以简单地进入在该表单的设计器文件中找到的生成表单代码,并拉出添加事件的行。这将是这个样子:

this.controlName.CheckedChanged += new System.EventHandler(this.controlName_CheckedChanged); 

然后把所有这些调用到您在窗体的构造函数中InitializeComponent调用后调用一个方法。

+0

我会小心,因为如果你在设计器类中弄乱了代码,你可能会以丑陋的方式破坏你的表单。它应该工作,但经常备份以防万一! – 2016-07-19 18:44:36

-3

我把一个公共变量在模块1文件 昏暗公共bolForm_LoadingTF布尔=真

在每个formLoad事件我把 bolForm_LoadingTF =真

在具有OnSelectedIndexChanged 事件每个控件我把若bolForm_LoadingTF =真然后退出子

在形式负载事件的结束我把 bolForm_LoadingTF =假

我可能打破了一堆规则,但这对我来说 。

-1

也许某些功能可以使用click事件而不是检查更改的事件。

1

还有一种方法:

Private Sub dgvGroups_CellValueChanged(sender As System.Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgvGroups.CellValueChanged 

    If Me.Visible = False Then Exit Sub ' Sub gets called on form load which causes problems 

    wksGroups.Cells(e.RowIndex + 1, 1) = dgvGroups.Item(e.ColumnIndex, e.RowIndex).Value 
    wksGroups.Cells(1, 5) = dgvGroups.RowCount 
2

对于radiobutton看到Hans Olsson answer

对于数字上下,像这样做

Private Sub myNumeric_ValueChanged(sender As Object, e As EventArgs) Handles myNumeric.ValueChanged 
     If myNumeric.Value >= 0 AndAlso myNumeric.IsHandleCreated Then 
      'Do the work 
     End If 
End Sub 

的关键词是myNumeric.ValueIsHandleCreated

+1

'IsHandleCreated'是这里的诀窍,比布尔黑客IMO更好。我在'ValueChanged'处理程序中使用'If CType(sender,NumericUpDown).IsHandleCreated Then ...'。 – Nepaluz 2017-01-23 16:37:36

0

刚在任何情况下ne仍然在搜索这个事件在初始化表单时被触发但是表单不可见,也就是说你有一个外键关系,你有一个缺省值需要的问题,每一行更新都会被触发。所以下面的代码为我工作....

if (Visible && !(e.ColumnIndex == 0)) 
     { 
      phoneEdited = true; 
      MessageBox.Show("A Phone entry has been entered"); 
     } 
相关问题