Vb.net 检查是否有任何控件已更改,并在表单关闭时保存数据

Vb.net 检查是否有任何控件已更改,并在表单关闭时保存数据,vb.net,winforms,dirty-checking,dirty-tracking,Vb.net,Winforms,Dirty Checking,Dirty Tracking,我们正在使用vb.net/dev express工具。我们有几个控件文本框、组合框等。。。我们不想检查每个更改的值,而是要检查所有控件并检查是否有任何内容已被编辑,然后在表单关闭时保存。下面是我试图实现这一点的一些代码。问题是,虽然技术上可行。。。它使用递归AddDirtyEvent(c),因此当我关闭表单并单击yes保存时。。由于多个控件,它多次调用messagebox。。。如果我把它拿出来,它就不会工作,也检测不到脏的变化。我只是想知道我如何才能让这个工作的方式,我想或者如果有一个更简单的方

我们正在使用vb.net/dev express工具。我们有几个控件文本框、组合框等。。。我们不想检查每个更改的值,而是要检查所有控件并检查是否有任何内容已被编辑,然后在表单关闭时保存。下面是我试图实现这一点的一些代码。问题是,虽然技术上可行。。。它使用递归AddDirtyEvent(c),因此当我关闭表单并单击yes保存时。。由于多个控件,它多次调用messagebox。。。如果我把它拿出来,它就不会工作,也检测不到脏的变化。我只是想知道我如何才能让这个工作的方式,我想或者如果有一个更简单的方法

 Dim is_Dirty As Boolean = False

  Private Sub AddDirtyEvent(ByVal ctrl As Control)

    For Each c As Control In ctrl.Controls
        If TypeOf c Is TextEdit Then
            Dim tb As TextEdit = CType(c, TextEdit)
            AddHandler tb.EditValueChanged, AddressOf SetIsDirty

        End If
        'If TypeOf c Is ComboBoxEdit Then
        '    Dim cb As ComboBoxEdit = CType(c, ComboBoxEdit)
        '    AddHandler cb.SelectedIndexChanged, AddressOf SetIsDirty

        'End If
        If c.Controls.Count > 0 Then
            AddDirtyEvent(c)
        End If

    Next

End Sub

Private Sub SetIsDirty(ByVal sender As System.Object, ByVal e As System.EventArgs)
    is_Dirty = True
End Sub

Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing

    If is_Dirty = True Then
        Dim dr As DialogResult = MessageBox.Show("Do you want save changes before leaving?", "Closing Well Info", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2)
        If dr = Windows.Forms.DialogResult.Yes Then
            SimpleButtonSave.PerformClick()
            Me.Close()
        End If
    End If
End Sub

代码中处理事件并设置脏标志的部分工作正常


您的消息框出现多次,因为您正在调用
Me.Close
事件处理程序中的
FormClosing
。调用
Close
再次递归触发FormClosing事件。只需移除
Me。关闭
;表单已经关闭。

作为一名ex-MS access程序员,我也非常渴望为vb.net开发一个表单脏属性的实现,我发现它更方便用户(我的用户已经习惯了)检测窗体上控件的更改或留下脏窗体并请求确认,而不是使用经典的编辑和保存按钮。 我以前在库中为textbox、combobox、listbox等创建了自定义控件。。。因为我喜欢有焦点的控件有不同的背景和缩放文本的能力等等

所以我添加了(文本框代码):

表单保存将调用Formdirty(me)=False 它仍然在测试阶段,仍然没有从用户那里得到确认,等等。。。 它是有效的,但由于我对.net编程非常陌生,所以欢迎任何评论或批评

rgds

>    Protected Overrides Sub OnModifiedChanged(e As EventArgs)
>        MyBase.OnModifiedChanged(e)
>        If _DirtyEnabled and Me.Modified Then FormDirty(Me) = Me.Modified
>    End Sub
>    Private _DirtyEnabled As Boolean = False
>    <Category("Misc"), Description("When Enabled triggers Dirty event for form"), Browsable(True)> _
>    Public Property DirtyEnabled As Boolean
>        Get
>            Return _DirtyEnabled
>        End Get
>        Set(value As Boolean)
>            DirtyEnabled = value
>        End Set
>    End Property
>    #Region "Dirty"
>    Private Structure FormInfo  ' used in DirtyForm dictionary to keep a list of dirty forms
>        Dim Name As String
>        Dim Time As Date
>        Dim Ctrl As String
>    End Structure
>    Private DirtyForms As New Dictionary(Of IntPtr, FormInfo)     ' key = form handle as the form could be opened more then once, value FormInfo
>
>     Public Property FormDirty(frm As Form) As Boolean
>        Get
>            If DirtyForms.Count > 0 Then
>                Return DirtyForms.ContainsKey(frm.Handle)
>            Else
>                Return False
>            End If
>        End Get
>        Set(IsDirty As Boolean)
>            EditDirtyForms(frm, IsDirty)
>        End Set
>    End Property
>
>    Public Property FormDirty(Ctrl As Control) As Boolean
>        Get
>            If DirtyForms.Count > 0 Then
>                 Return DirtyForms.ContainsKey(Ctrl.FindForm.Handle)
>             Else
>                 Return False
>             End If
>        End Get
>        Set(IsDirty As Boolean)
>            EditDirtyForms(Ctrl.FindForm, IsDirty, Ctrl.Name)
>        End Set
>    End Property
>
>    Private Sub EditDirtyForms(frm As Form, IsDirty As Boolean, Optional CtrlName As String = Nothing)
>        If IsDirty Then
>            If DirtyForms.Count = 0 OrElse Not DirtyForms.ContainsKey(frm.Handle) Then
>                Dim Info As New FormInfo With {.Name = frm.Name, .Time = Now, .Ctrl = CtrlName}
>                DirtyForms.Add(frm.Handle, Info)
>            End If
>        ElseIf DirtyForms.Count > 0 Then
>            If DirtyForms.ContainsKey(frm.Handle) Then DirtyForms.Remove(frm.Handle)
>        End If
>    End Sub
>
>    Public Function DirtyFormList() As String
>        Dim p As New FormInfo, s As String = String.Empty
>        If DirtyForms.Count > 0 Then
>            For Each f As KeyValuePair(Of IntPtr, FormInfo) In DirtyForms
>                s &= f.Value.Name & cSpace & If(f.Value.Ctrl, String.Empty) & ": " & f.Value.Time & vbNewLine
>            Next
>        End If
>        Return s
>    End Function
>
>    Public Function DirtyFormCount() As Integer
>        Return DirtyForms.Count
>    End Function
> #End Region