SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

japan.internet.com翻訳記事

Visual Studio 2005のフォームにおけるBindingNavigatorの拡張

BindingNavigatorによるデータアクセスアプリケーションの開発効率アップ

自動保存(AutoSave)機能の実装

 2つ目の問題は、1つ目よりも少し厄介です。BindingSourceコンポーネントには「データが修正されたかどうかを示すフラグ」がないため、これが大きな問題となっています。グリッドの場合は、RowLeaveイベントの際にIsRowDirtyフラグを確認することができますが、バインドの詳細に関するフォーマットコントロールには、それに相当するフラグがありません(このことをバグとして報告したところ、Microsoftからは、将来のバージョンで修正予定であるという返事が来ました)。というわけで、今回作成するコントロールでは、データが編集されたときにセットできるフラグを追加する必要がありました。

  1. 画面上で右クリックし、[View Code]をクリックしてコードビハインドページ(分離コードページ)を開きます。次のコードを追加して、このコントロールに必要となるIsDataDirtyプロパティを作成します。
  2. Private _IsDataDirty As Boolean = False
    Public Property IsDataDirty() As Boolean
        Get
            Return _IsDataDirty
        End Get
        Set(ByVal value As Boolean)
            _IsDataDirty = value
            If BindingNavigatorSaveItem.Enabled <> _IsDataDirty Then
                BindingNavigatorSaveItem.Enabled = _IsDataDirty
            End If
        End Set
    End Property
    
  3. このフラグをセットするには、BindingSourceのBindingCompleteイベントをインターセプトする必要があります。実際のところ、これは不経済なイベントです。というのは、レコードを変更するたびに、バインドされているコントロール1つ1つが呼び出されるためです。しかし、データが更新されてコントロールからデータセットに戻される際にもこのイベントが呼び出されます。つまり、本稿で必要となる情報を提供してくれるわけです。次のメソッドではBindingCompleteイベントを処理し、データが編集されている場合はプロパティをセットします。
  4. Private Sub BindingComplete(ByVal sender As Object, _
        ByVal e As BindingCompleteEventArgs)
        'is this a return from the control to the dataset?
        If e.BindingCompleteContext = BindingCompleteContext.DataSourceUpdate Then
            'was it successful and not for a read only control?
            If e.BindingCompleteState = BindingCompleteState.Success And _
                    Not e.Binding.Control.BindingContext.IsReadOnly Then
                IsDataDirty = True
            End If
        End If
    End Sub
    
  5. ここでHandles句を使ってイベントをサブスクライブすることも可能ですが、今回のサンプルではVisual Basic内でエラーが発生するのを回避するために、BindingSourceが定義されるのを待ってからハンドラを割り当てるようにします。BindingSourceのsetメソッドのハンドラセクションに、次のコードを追加してください。
  6.     AddHandler _BindingSource.BindingComplete, AddressOf BindingComplete
        AddHandler _BindingSource.PositionChanged, AddressOf bs_PositionChanged
    
  7. 2行目で追加するハンドラによって、ユーザーが新しいレコードに移動したときに前のレコードを保存できるようになります。レコードがいつ変更されたかを知るために使うことのできるイベントは、いくつかあります。例えば、CurrentChanged、CurrentItemChanged、PositionChangedなどです。ここで最良の選択は、PositionChangedです。これらのイベントに関する問題は、どれもが「過去形」で実行されることです。つまり、「レコードが既に変更されてしまってからイベントが呼び出される」ということです。そのため、レコードを変更せずに残しておく手段がありません。最善の措置は、前のレコードのデータを保存することです。
  8. 次のメソッドでは、バインディングソースを対象にPositionChangedイベントを処理し、フラグをチェックして、必要に応じて保存メソッドを呼び出します。
  9. Private Sub bs_PositionChanged(ByVal sender As Object, ByVal e As EventArgs)
        If (_IsDataDirty And Not _DataTable Is Nothing) Then
            SaveItem_Click(New Object(), New EventArgs())
        End If
    End Sub
    

保存するかどうかをユーザーに確認する

 3つ目の問題は、「変更されたデータを保存するか、変更前の状態に戻すか」という確認メッセージをユーザーに表示しなければならない場合が考えられるということです。もちろん、この確認メッセージの表示はオプション機能にすべきであるため、まずはAutoSaveというプロパティを追加する必要があります。これがfalseの場合は、保存するかどうかの確認メッセージがユーザーに表示されます。

  1. コードページのプロパティ定義の部分に次のコードを追加します。
  2. Private _AutoSaveFlag As Boolean
    Public Property AutoSaveFlag() As Boolean
        Get
            Return _AutoSaveFlag
        End Get
        Set(ByVal value As Boolean)
            _AutoSaveFlag = value
        End Set
    End Property
    
  3. 前述のPositionChangedイベント用のハンドラを修正して、このフラグをチェックし、フラグが有効である場合は保存確認メッセージを表示するようにします。
  4. Private Sub bs_PositionChanged(ByVal sender As Object, ByVal e As EventArgs) _
        Handles _BindingSource.PositionChanged
    
        If (_IsDataDirty And Not _DataTable Is Nothing) Then
            Dim msg As String = "Do you want to save edits to the previous record?"
            If _AutoSaveFlag Or MessageBox.Show(msg, "Confirm Save", _
                MessageBoxButtons.YesNo) = DialogResult.Yes Then
    
                SaveItem_Click(New Object(), New EventArgs())
            Else
                _DataTable.RejectChanges()
                MessageBox.Show("All unsaved edits have been rolled back.")
                _IsDataDirty=False
            End If
        End If
    End Sub
    
  5. これで保存確認ができるようになりましたが、レコードの削除の際にも、削除を確認する必要があります。そのためには、まず標準の削除メソッドを無効にする必要があります。ユーザーコントロールのデザイナビューで、BindingNavigatorのツールストリップを選びます。プロパティパネルの[Items]セクションにある[DeleteItem]でドロップダウンリストを表示して、[(none)]を選びます。
  6. さらに、ユーザーに確認メッセージを表示した後にのみレコードを削除するメソッドが必要です。ツールバーにある[Delete]アイコン(赤い×)をダブルクリックしてコードスタブを作成し、次のコードを追加します。
  7. Private Sub BindingNavigatorDeleteItem_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles BindingNavigatorDeleteItem.Click
    
        Dim msg As String = "Are you sure you want to delete the current record? "
        If _AutoSaveFlag Or MessageBox.Show(msg, "Confirm Delete", _
            MessageBoxButtons.YesNo) = DialogResult.Yes Then
    
            'Delete the current record
            _BindingSource.RemoveCurrent()
            CType(_DataTable, Win._Interface.ITableUpdate).Update()
        End If
    End Sub
    

次のページ
ルックアップリストの追加

この記事は参考になりましたか?

japan.internet.com翻訳記事連載記事一覧

もっと読む

この記事の著者

japan.internet.com(ジャパンインターネットコム)

japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.comEarthWeb.com からの最新記事を日本語に翻訳して掲載するとともに、日本独自のネットビジネス関連記事やレポートを配信。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

David Catherman(David Catherman)

CMI Solutions所属。データベースアプリケーションのデザイン/開発に20年以上の経験を持ち、ここ4、5年は特にMicrosoft .NETとSQL Serverに仕事が集中している。現在はCMI Solutionsのアプリケーション設計者および上級開発者であり、Visual Studioと...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/431 2006/08/22 15:50

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー