1

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

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

但问题是有超过 30 个组件和创建方法来处理每个组件的事件,这对我来说似乎没有效果。

4

3 回答 3

0

这是我如何使用自定义类执行此操作的示例。这只是读取 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 中,所以其余的会很容易。请注意,当表单关闭时,我可以轻松地遍历每条记录以查看是否有更改。如果您只有一条记录,您甚至不必循环,只需询问它是否脏。

于 2013-10-25T15:16:17.807 回答
0

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

为了避免必须为每个控件编写代码(检查时),您可以在 [Tab Page Name].Controls() 中的每个控件上执行 for 循环。

另一种方法是通过添加 IsDirty 属性并覆盖验证事件来扩展每个控件。然后你可以设置它,如果它改变了。您可能还需要一种方法来重置 IsDirty 属性。

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

于 2013-10-24T14:48:18.313 回答
0

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

但是,对于分布在 30 个组件中的有效性问题,您应该考虑滚动您自己的组件,这些组件继承自暴露IsDirty属性或类似属性的基类。关闭时,您可以循环浏览选项卡上的所有控件以查看是否已IsDirty设置为true.

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

于 2013-10-24T14:24:46.517 回答