1

私のアプリケーションには、いくつかのタブを持つ TabControl があります。各タブには多くのコンポーネントが含まれています。アプリケーションが閉じている場合、コンポーネントの値が変更されたかどうかを確認したいと思います。その場合、ユーザーに保存するかどうかを尋ねます。

この状況をどのように解決するか知りたいです (アプリケーションが閉じているときの標準的な動作であるため)。いくつかのフラグ (bool) があると思い、各コンポーネントにイベント ValueChanged を設定しました。このイベントを処理するメソッドが起動されると、このフラグは true に設定されます。アプリケーションを閉じる場合、フラグが true かどうかのみを確認します。

しかし問題は、30 以上のコンポーネントがあり、各コンポーネントにイベントを処理するメソッドを作成することです。

4

3 に答える 3

0

各コントロールのテキスト/値を入力するときは、TAG にも同じ値を入力します。次に、タグを各コントロールのテキスト/値と比較して、何かが変更されたかどうかを確認できます。

コントロールごとにコードを記述する必要がないようにするには (チェックするとき)、[Tab Page Name].Controls() で各コントロールに対して for ループを実行します。

これを行うもう 1 つの方法は、IsDirty プロパティを追加し、検証イベントをオーバーライドして、各コントロールを拡張することです。変更された場合は、これを設定できます。IsDirty プロパティをリセットするメソッドが必要な場合もあります。

さらに別の方法として、私は常にクラスにバインドします。これにより、コードのエラーが発生しにくくなり、インテリセンスが得られます。また、このように簡単に投入できる機能がたくさんあります。次に、カスタム クラスに BIND します。

于 2013-10-24T14:48:18.313 に答える
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 にデータを入れたので、残りは簡単です。フォームが閉じているときに、すべてのレコードをループして、変更があったかどうかを簡単に確認できることに注意してください。レコードが 1 つしかない場合は、ループする必要さえありません。それがダーティかどうかを確認するだけです。

于 2013-10-25T15:16:17.807 に答える
0

ブール値フラグと ValueChanged イベントで正しい軌道に乗っています。私の知る限り、これがこの種の事態に対処する唯一の方法です。これを実現するには、イベントの処理を 1 回記述し、必要に応じてコンポーネントを何度もコピー アンド ペーストします。

ただし、30 個のコンポーネントに分散した場合の有効性の問題については、IsDirtyプロパティなどを公開する基本クラスから継承する独自のコンポーネントをローリングすることを検討する必要があります。閉じるときに、タブのすべてのコントロールをループして、にIsDirty設定されているものを確認できますtrue

残念ながら、既にインターフェイスを作成していることを考えると、どちらのアプローチも現在のジレンマを解決しません。

于 2013-10-24T14:24:46.517 に答える