简体   繁体   English

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

[英]Check if any control has changed and save data upon form closing

We are using vb.net / dev express tools.我们正在使用 vb.net/dev express 工具。 We have several controls textboxes, combos etc... instead of checking each value changed we want to go through all controls and check if anything has been edited, then save upon form closing.我们有几个控件文本框、组合等......而不是检查每个更改的值,我们想要查看所有控件并检查是否有任何内容被编辑,然后在表单关闭时保存。 Below is some code i have tried to accomplish this.下面是我试图完成此操作的一些代码。 Problem is, although it technically works... it uses recursion AddDirtyEvent(c) , so when i go to close the form and click yes to save.. it calls that messagebox multiple times due to multiple controls... if i take that out , it won't work and detect the dirty change.问题是,虽然它在技术上有效......它使用递归 AddDirtyEvent(c) ,所以当我去关闭表单并单击是保存......由于多个控件,它多次调用该消息框......如果我接受out ,它不会工作并检测到脏变化。 I'm just wondering how can i get this to work the way i want or if there is an easier way...我只是想知道如何让它按照我想要的方式工作,或者是否有更简单的方法......

 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

The part of your code that handles the events and sets the dirty flag works OK.处理事件和设置脏标志的代码部分工作正常。

Your MessageBox appears multiple times because you are calling Me.Close within the FormClosing event handler.您的 MessageBox 出现多次,因为您在FormClosing事件处理程序中调用Me.Close Calling Close triggers the FormClosing event again - recursively.调用Close再次触发 FormClosing 事件 - 递归。 Just remove the Me.Close ;只需删除Me.Close ; the form is already closing.表格已经关闭。

As an ex MS access programmer I was also quite eager to develop an implementation of a form dirty property for vb.net, I find it more user friendly (and my users are used to it) to detect change of a control on a form or leaving a dirty form and ask for confirmation rather then the classical edit and save buttons.作为一名前 MS 访问程序员,我也非常渴望为 vb.net 开发表单脏属性的实现,我发现它对用户更友好(我的用户已经习惯了)来检测表单上的控件更改或留下一个肮脏的表格并要求确认而不是经典的编辑和保存按钮。 I previously created custom controls in a library for textbox, combobox, listbox etc... as I like the control having the focus to have a different background and ability to zoom text etc...我以前在一个库中为文本框、组合框、列表框等创建了自定义控件......因为我喜欢控件具有不同的背景和缩放文本等的能力......

So I added to them (textbox code):所以我添加了它们(文本框代码):

>    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

This is for a textbox, For combobox and listbox I used the SelectIndexChanged event.这是一个文本框,对于组合框和列表框,我使用了 SelectIndexChanged 事件。 If the DirtyEnabled Property is set to True then any change would trigger a call of FormDirty property.如果 DirtyEnabled 属性设置为 True,则任何更改都会触发 FormDirty 属性的调用。 Then in a public module of the library:然后在图书馆的公共模块中:

>    #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

A forms save would call Formdirty(me) = False It's still in test phase and still misses asking confirmation from the user etc... It works but as I am quite new in .net programming any comment or critic is very welcome.表单保存将调用 Formdirty(me) = False 它仍处于测试阶段,仍然错过向用户询问确认等......它有效,但由于我在 .net 编程中很新,任何评论或评论都非常受欢迎。

rgds rgds

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM