Vb.net 检查表单中的选择/文本是否已更改

Vb.net 检查表单中的选择/文本是否已更改,vb.net,controls,textchanged,dirty-data,Vb.net,Controls,Textchanged,Dirty Data,我有一个表单,上面有大约20个控件(ComboBox,TextBox,等等),我已经预先加载了数据。这将显示给用户,并使他们能够更改任何字段 我不知道怎样才能最好地认识到已经发生了变化。经过一些研究,我发现了TextBox.TextChanged,并设置了标志IsDirty=True或类似的东西 我不认为这将是100%防弹的,因为用户可能会更改值,然后返回并将其更改为最初加载时的状态。我一直在考虑将当前数据保存到.Tag,然后将其与用户单击“取消”时输入的.Text进行比较,询问他们是否愿意保存

我有一个表单,上面有大约20个控件(
ComboBox
TextBox
,等等),我已经预先加载了数据。这将显示给用户,并使他们能够更改任何字段

我不知道怎样才能最好地认识到已经发生了变化。经过一些研究,我发现了
TextBox.TextChanged
,并设置了标志
IsDirty=True
或类似的东西

我不认为这将是100%防弹的,因为用户可能会更改值,然后返回并将其更改为最初加载时的状态。我一直在考虑将当前数据保存到
.Tag
,然后将其与用户单击“取消”时输入的
.Text
进行比较,询问他们是否愿意保存更改

这是我的代码:

Private Sub Form1_Load(ByVal sender as Object, byVal e as System.EventArgs)Handles MyBase.Load
    For Each ctr as Control in me.Controls
       if typeof ctr is TextBox then
         ctr.tag=ctr.text
       end if
    Next 
End Sub
这是用户单击“取消”时的代码:

Private Sub CmdCancel\u Click(ByVal sender作为对象,ByVal e作为System.EventArgs)处理CmdCancel。单击
对于每个ctr作为Me.Controls中的控件
如果ctr的类型为文本框,则
如果ctr.tag.tostring ctr.text,则
MsgBox(“是否要保存项目”,YesNo)
如果结束
如果结束
下一个
端接头
这是一种有效的方法吗?可以信赖吗?如果有人有更好的主意,我很乐意听

看看这个:

For Each txtBox In Me.Controls.OfType(Of TextBox)()
    If txtBox.Modified Then
        'Show message
    End If
Next
编辑

看看这个。如果您想要
.Tag
属性的替代方法,您可能会感兴趣:

'Declare a dictionary to store your original values
Private _textboxDictionary As New Dictionary(Of TextBox, String)

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

    'You would place this bit of code after you had set the values of the textboxes
    For Each txtBox In Me.Controls.OfType(Of TextBox)()
        _textboxDictionary.Add(txtBox, txtBox.Text)
    Next

End Sub
Public Class myTextBox
    Inherits System.Windows.Forms.TextBox
    Private Property OriginalText As String
    Public ReadOnly Property TextAltered As Boolean
        Get
            If OriginalText.Equals(MyBase.Text) Then
                Return False
            Else
                Return True
            End If
        End Get
    End Property
    Public Overrides Property Text As String
        Get
            Return MyBase.Text
        End Get
        Set(value As String)
            Me.OriginalText = value
            MyBase.Text = value
        End Set
    End Property
End Class
然后使用此项找出原始值并与新值进行比较:

For Each txtBox In Me.Controls.OfType(Of TextBox)()
    If txtBox.Modified Then
         Dim oldValue = (From kp As KeyValuePair(Of TextBox, String) In _textboxDictionary
                         Where kp.Key Is txtBox
                         Select kp.Value).First()
         If oldValue.ToString() <> txtBox.Text Then
             'Show message
         End If

    End If
Next
(文本框的)类型的Me.Controls.中的每个txtBox(
)
如果txtBox.Modified则
Dim oldValue=(来自kp,作为_textboxDictionary中的(文本框、字符串的)KeyValuePair
其中kp.Key是txtBox
选择kp.Value)
如果oldValue.ToString()txtBox.Text,则
'显示消息
如果结束
如果结束
下一个

我知道这已经有了一个公认的答案,但我认为应该解决关于检查实际文本值是否已更改的部分。选中“已修改”将显示是否对文本进行了任何更改,但如果用户(例如)添加字符,然后将其删除,则将失败。我认为一个很好的方法是使用一个自定义控件,所以这里有一个简单控件的示例,它在以编程方式更改textbox时存储其原始文本,并且具有TextChanged属性,可以检查该属性以显示用户的修改是否实际导致文本与其原始状态不同。这样,每次您自己用数据填充文本框时,您设置的值都会被保存。准备好后,只需检查TextChanged属性:

'Declare a dictionary to store your original values
Private _textboxDictionary As New Dictionary(Of TextBox, String)

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

    'You would place this bit of code after you had set the values of the textboxes
    For Each txtBox In Me.Controls.OfType(Of TextBox)()
        _textboxDictionary.Add(txtBox, txtBox.Text)
    Next

End Sub
Public Class myTextBox
    Inherits System.Windows.Forms.TextBox
    Private Property OriginalText As String
    Public ReadOnly Property TextAltered As Boolean
        Get
            If OriginalText.Equals(MyBase.Text) Then
                Return False
            Else
                Return True
            End If
        End Get
    End Property
    Public Overrides Property Text As String
        Get
            Return MyBase.Text
        End Get
        Set(value As String)
            Me.OriginalText = value
            MyBase.Text = value
        End Set
    End Property
End Class

有一些内在的方式。一个是
Modified
属性。您还可以与源代码(如数据表)进行比较,而不必使用
标记
。另一个原因是,如果使用绑定控件,datatable会将行标记为已更改。不过,我认为它也不会捕捉回更改的情况。您可以向项目中添加一个自定义控件,该控件继承textbox,并重载其.Text方法,以便在每次以编程方式设置文本时将文本框的内容保存到OriginalText属性。然后你只需要添加另一个只读属性,它将文本框的当前文本与其原始文本进行比较,如果有任何文本发生了更改,则返回True。我正在考虑使用类路径,我很高兴有人将其显示为一个答案,因为技术上更好。很遗憾标准控件还不支持它,因为我相信很多人都会喜欢它。