在窗体关闭上保存组件的更改值



在我的应用程序中,我有一个带有一些选项卡的 TabControl。每个选项卡都包含许多组件。如果应用程序正在关闭,我想检查是否有任何组件的值已更改。如果是这样,我会问用户是否要保存它。

我想知道您如何解决这种情况(因为它是应用程序关闭时的标准行为)。我以为我有一些标志(布尔值),我为每个组件设置了一个事件 ValueChanged。如果触发处理此事件的方法,则此标志设置为 true。在关闭应用程序的情况下,我只会检查标志是否为真。

但问题是有 30 多个组件和创建方法处理每个组件的事件对我来说似乎没有影响。

你走在布尔标志和 ValueChanged 事件的正确轨道上。据我所知,这确实是处理这种事情的唯一方法。为此,您只需编写一次事件的处理,然后根据需要一遍又一遍地复制和粘贴组件。

但是,对于分布在 30 个组件中的有效性问题,您应该考虑滚动自己的组件,这些组件继承自公开IsDirty属性或类似属性的基础类。关闭时,您可以遍历选项卡上的所有控件,以查看任何IsDirty设置为 true 的控件。

不幸的是,鉴于您已经创建了界面,这两种方法都无法解决您当前的困境。

为每个控件填写文本/值时,还要使用相同的值填充 TAG。然后,可以将 TAG 与每个控件的文本/值进行比较,以查看是否有任何更改。

为了避免必须为每个控件编写代码(在检查时),您可以在 [选项卡页名称] 中的每个控件上执行 for 循环。控件()。

执行此操作的另一种方法是通过添加 IsDirty 属性并重写验证事件来扩展每个控件。然后,如果它发生了变化,您可以设置它。 您可能还需要一种方法来重置 IsDirty 属性。

还有一种方式,我总是绑定到一个类,它只是让我的代码不那么容易出错,并给我智能感。还为您提供了大量功能,您可以像这样轻松投入。然后只需绑定到您的自定义类。

下面是如何使用自定义类执行此操作的示例。这只是阅读 csv 并编写它的一个例子,但回答您的问题的关键在于"脏"代码。

Imports System.ComponentModel
Public Class Form1
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
        'On form load, open the file and read the data
        Using SR As New System.IO.StreamReader("Test.csv")
            Do While SR.Peek >= 0
                'Put each line into it's own instance of the class
                BindingSource1.Add(New MyData(SR.ReadLine))
            Loop
        End Using
    End Sub
    Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
        'When closing, see if any data has been changed and ask to save
        Dim bDirty As Boolean = False
        For Each dat As MyData In BindingSource1
            If dat.IsDirty Then
                bDirty = True
                Exit For
            End If
        Next
        If bDirty Then
            'Example code for saving
            Select Case MessageBox.Show("Do you want to save your changes?", "Save Changes", MessageBoxButtons.YesNoCancel)
                Case Windows.Forms.DialogResult.Cancel
                    e.Cancel = True
                Case Windows.Forms.DialogResult.Yes
                    'Here you should remove the old file, I like to rename it to BAK, 
                    '  save the new file, then you can get rid of it. 
                    '  Just in case there is a problem saving.
                    If System.IO.File.Exists("Test.csv") Then System.IO.File.Delete("Test.csv")
                    Using SW As New System.IO.StreamWriter("Test.csv", False)
                        For Each dat As MyData In BindingSource1
                            SW.WriteLine(dat)
                        Next
                    End Using
            End Select
        End If
    End Sub
End Class
Public Class MyData
    Implements INotifyPropertyChanged
    'Event that implements INotifyPropertyChanged. This tells the binding to refresh a property in the UI.
    Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged
    Public Sub New(ByVal SomeDataToLoad As String)
        'Take you data and parse it or whatever into the various properties
        'This example uses a comma-seperated string
        Dim sWords As String() = SomeDataToLoad.Split(",")
        _FirstName = sWords(0)
        _LastName = sWords(1)
    End Sub
    ''' <param name="PropertyName">Case-Sensative property name</param>
    Public Sub ForcePropertyChanged(ByVal PropertyName As String)
        RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs(PropertyName))
    End Sub
    Private _IsDirty As Boolean
    Public ReadOnly Property IsDirty As Boolean
        Get
            Return _IsDirty
        End Get
    End Property
    ''' <summary>Override the ToString method for getting the data back out, in this case as comma seperated again. You can then write this to file or whatever.</summary>
    Public Overrides Function ToString() As String
        Return FirstName & "," & LastName
    End Function
    '--Properties you can bind to------------------------------------------------
    Private _FirstName As String
    Public Property FirstName As String
        Get
            Return _FirstName
        End Get
        Set(value As String)
            _FirstName = value
            _IsDirty = True
            ForcePropertyChanged("FirstName")
        End Set
    End Property
    Private _LastName As String
    Public Property LastName As String
        Get
            Return _LastName
        End Get
        Set(value As String)
            _LastName = value
            _IsDirty = True
            ForcePropertyChanged("LastName")
        End Set
    End Property
End Class

我没有在这里讨论如何绑定,你可以在网络上找到它,但我确实将数据放在 BindingSource 中,所以其余的都很容易。请注意,当表单关闭时,我可以轻松地遍历每条记录以查看是否有更改。如果你只有一张唱片,你甚至不必循环,只要问它是否脏。

最新更新