none
他のフォームの値を参照するには RRS feed

  • 質問

  • こんにちは。

    検索用のフォーム(form1)と検索で指定した患者のデータを表示するフォーム(form2)があります。

    form2にform1のリストビューで選択した患者コードを元にデータセットにデータを取得して、form2のテキストボックスなどにデータを表示するプログラムがあります。(form1にある「表示」というボタンを押すと、form2が表示され、患者データが表示されます。)

    現在、form2にPublic Subで患者データをデータセットに取得し、フォーム上のテキストボックスなどに表示をするようになっており、form1のボタンを押すことで、form2のプログラムをcallするようにしてあります。

    Accessから移行を勉強中なので、とりあえずはプログラムは動いているのですが、果たしてこれでいいものかということで質問をしました。以下に私の記述したプログラムを提示しますので、一般的にはこのように記述するという方法がありましたら、ご教授いただけますでしょうか。

    手持ちの参考書やネットでは調べることができませんでした。

    form1に記述

    Private Sub btn_Call_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn_Call.Click
            Dim frm As frm_ptbasedata = frm_ptbasedata  ← ここの記述

            frm.Show()
            Call frm.Disp_PtDataDS2()
        End Sub

    form2に記述

        'データセットを利用して、データを取得
        Public Sub Disp_PtDataDS2()
            Dim Cn As New SqlConnection(My.MySettings.Default.Con)
            Dim Sc As New SqlCommand
            Dim Da As New SqlDataAdapter()
            Dim Ds As New DataSet()
            Dim DRow As DataRow
            Dim frm As frm_ptsearch = frm_ptsearch  ← ここの記述

            '選択コマンドをセットする
            With Sc
                .CommandText = "sp_disp_ptdata"
                .CommandType = CommandType.StoredProcedure
                .Connection = Cn
                .Parameters.Add("@pt_code", SqlDbType.VarChar).Value = _
                                        frm.lst_PtIchiran.SelectedItems.Item(0).Text
            End With

            'データアダプターの選択コマンドにセット
            Da.SelectCommand = Sc

            Da.Fill(Ds, "t_patient")
            DRow = Ds.Tables("t_patient").Rows.Item(0)   

            With Me
                .txt_PtID.Text = DRow("pt_code")
                .txt_PtName.Text = DRow("pt_name")
            End With
        End Sub

    どうか、よろしくお願いいたします。

    2007年2月11日 2:38

回答

  • ご回答ありがとうございます。

    少しずつしか進めないとは思いますが、がんばってみたいと思います。

    又、困ったときはよろしくお願い致します。

    本当にありがとうございました。

    2007年2月13日 2:01

すべての返信

  •  TI-cb400s さんからの引用
    Accessから移行を勉強中なので、とりあえずはプログラムは動いているのですが、果たしてこれでいいものかということで質問をしました。以下に私の記述したプログラムを提示しますので、一般的にはこのように記述するという方法がありましたら、ご教授いただけますでしょうか。

    方法はいろいろあるとは思いますが、
    分散アプリケーション開発という開発手法があります。
    分散アプリケーションの構築 - 実践的アーキテクチャ: 階層化


    • プレゼンテーション層
    • ビジネス ロジック層
    • データ アクセス層

    といったように処理を n階層に分けて実装します。
    これを意識するだけで十分だと思います。

    今回の例でいけば、
    form1 と form2 はプレゼンテーション層にあたります。
    form1 には患者を選択する処理のみ記述し、
    form2 には患者情報を表示する処理のみ記述します。

    患者情報を取得する処理はプレゼンテーション層にあたるフォームに記述せずに
    データアクセス層のクラスを作成してそこに記述します。

    処理の流れでいうとこのような感じになると思います。


    • form1 で患者を選択する。
    • 選択した患者をもとに、患者情報を取得する処理を呼び出す。
    • form1 から form2 に取得した患者情報を渡す。
    • form2 は渡された患者情報を表示する。

    2007年2月11日 7:02
  • ご回答ありがとうございます。

     ダッチ さんからの引用


    • form1 で患者を選択する。
    • 選択した患者をもとに、患者情報を取得する処理を呼び出す。
    • form1 から form2 に取得した患者情報を渡す。
    • form2 は渡された患者情報を表示する。

    なるほど。このように考えていくわけですね。

    しかし、このようにすると疑問があるのですが、今回はDatasetを使ってデータを取得しているのですが、その場合の更新や新規追加の処理はどこに記述することになるのでしょうか。

    できれば、検索用のフォーム(form1)は患者を選択した段階で表示をしないようにして、form2に更新又は新規追加のボタンを用意しておきたいのですが、その場合は一旦form1を閉じてしまうのではなく、非表示にしてform1側に更新や新規追加の処理も記述しておき、その処理を呼び出すということをするのでしょうか。

    ADO.NETについての本を読んだのですが、このような一連の流れについての説明がなく、Accessのときは、検索用のフォームは患者を指定するのみで、標準モジュールに患者情報を取得する処理を記述しておき、患者情報を表示するフォームに更新・追加の処理を記述していたので、どうにもDataSetを使うやり方がぴんときません。

    どうか、よろしくお願いします。

    また、

    Dim frm as frm_ptsearch=frm_ptsearch

    という記述の仕方で問題はないのでしょうか。

    2007年2月11日 9:32
  •  TI-cb400s さんからの引用
    しかし、このようにすると疑問があるのですが、今回はDatasetを使ってデータを取得しているのですが、その場合の更新や新規追加の処理はどこに記述することになるのでしょうか。

    できれば、検索用のフォーム(form1)は患者を選択した段階で表示をしないようにして、form2に更新又は新規追加のボタンを用意しておきたいのですが、その場合は一旦form1を閉じてしまうのではなく、非表示にしてform1側に更新や新規追加の処理も記述しておき、その処理を呼び出すということをするのでしょうか。

    DB の更新処理などもデータを取得するクラスに合わせて記述します。
    そして、form2 から更新処理を呼び出せば良いと思います。

    form1 でデータを取得するには、別のクラスに実装されている処理を呼んだだけです。
    form2 からも更新処理を行いたい場合は、別のクラスに実装されている更新処理を呼んであげれば良いでしょう。

    あくまでもデータアクセスに関する処理を別のクラスに実装しておき、
    その処理を使用する側(今回はフォーム)ではその処理を呼び出すだけにしておくと良いと思います。

    .NET Freamwork 2.0 からは TableAdapter というクラスが提供されています。
    TableAdapter の Update メソッド に DataSet を渡すことで更新処理が行われます。
    これを利用してデータアクセスをするのが一般的だと思います。

    なお TableAdapter を使用した場合のデータ取得や更新処理などは全て
    VisualStudio2005 からウィザードを使用して自動作成することも可能です。

    このあたりはネット上でも書籍でも調べることは出来ると思います。

     TI-cb400s さんからの引用
    また、

    Dim frm as frm_ptsearch=frm_ptsearch

    という記述の仕方で問題はないのでしょうか。

    普通このような記述はしませんね。
    右辺の frm_ptsearch は frm_ptsearch クラスの暗黙のインスタンスが作成されてしまいます。
    私なら、
     
    Dim frm As frm_ptsearch = New frm_ptsearch

    このように New を付けて明示的にインスタンスを生成します。
    暗黙のインスタンスは理解しにくいため、予期せぬバグを生む可能性もあります。

    2007年2月11日 13:49
  • ご回答ありがとうございます。

     ダッチ さんからの引用

    あくまでもデータアクセスに関する処理を別のクラスに実装しておき、
    その処理を使用する側(今回はフォーム)ではその処理を呼び出すだけにしておくと良いと思います。

    これは、form1でもform2でもなく、モジュールにデータアクセスに関する処理を記述するということでしょうか。(クラスの概念がいまいち理解できておらずおかしなことをいっているとは思うのですが。)それとも、たとえばform1のコードの中では、はじめひとつのクラスの中にLoadのイベントなどが入っているのですが、そのクラスの次に新たに、Class~といった記述を加えればよいのでしょうか。

     

    2007年2月11日 22:34
  • 無理にモジュールを使用しなくても、クラスを使用すれば良いです。

    例えばデータアクセス用のクラスとして DataAccess というクラスがあったとします。
    DataAccess にはデータを取得する Fill メソッドと データを更新する Update メソッドが実装されています。


    Public Class DataAccess
     
        Public Function Fill(ByVal dataTable As DataTable) As Integer
            ' 取得処理
        End Function

        Public Function Update(ByVal dataSet As DataSet) As Integer
            ' 更新処理
        End Function
     
    End Class

    フォーム側ではデータを取得したければ、 DataAccess の Fill メソッド を
    データを更新したければ、DataAccess の Update メソッド を呼び出すだけです。
    フォームには一切データを取得したり更新したりする処理は記述されていません。


    Public Class Form1
     
        ' データアクセスを行うクラス 
        Private m_DataAccess As New DataAccess
     
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            ' データを取得するため、DataAccess クラスの Fill メソッドを呼び出す
            Me.m_DataAccess.Fill(...)
        End Sub
     
        Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
            ' データを更新するため、DataAccess クラスの Update メソッドを呼び出す
            me.m_DataAccess.Update(...)
        End Sub
     
    End Class

    雰囲気をつかんで頂けたでしょうか。

    DataAccess クラスを患者情報用に作成すれば、患者情報のデータアクセスを行うクラスが作成され、
    職員情報用に作成すれば、職員情報のデータアクセスを行うクラスが作成されるでしょう。

    そして一度患者情報のデータアクセスクラスを作成しておけば、
    他のクラス(form1 や form2)から患者情報のデータアクセスを
    メソッドを呼ぶだけで行えるようになります。

    今回例であげた DataAccess クラスは前回にも述べた、 TableAdapter にあたり
    VisualStudio2005 から自動生成することが可能です。
    自動生成されたコードを見ると、いろいろ役に立つ情報があると思います。

    ここで一つ訂正があります。
    TableAdapter クラス というクラスはありませんでした。
    VisualStudio2005 から自動生成することで作成されるデータアクセスを行うクラスの名前でした。
    不適切な内容があり申し訳ありません。

    2007年2月12日 4:10
  • ご回答ありがとうございます。

    漠然とではありますが、クラスの輪郭程度はつかめた気がします。

    他のホームページなどでクラスについて書かれているものがあったので一通り目を通したのですが、クラスと標準モジュールにPublicで作成したプログラムとの違いと、先の返答の例で書かれていた、患者用と職員用のデータアクセスを行うクラスを作りたい場合はDataAccessクラスを2つ作る必要があるのか、それとも、DataAccessというクラスひとつで対応が可能なのかという2点です。

    どうにも、クラスという概念に初めて触れたのでよくわからないのですが、今回私が患者データをform2に表示するに際して、

    患者の選択 → ストアドを元に患者データをデータセット(データテーブル)に取得 → form2に表示

    という段階を踏んでいるのですが、もし、DataAccessというクラスひとつでいろいろなものに対応できるとすると、データの取得対象が違えば、ストアドも当然異なると思うのですが、このストアドはどこで渡す(変更する)のでしょうか。

    もし、DataAccessというクラスをデータ取得別にいくつも作成をする必要がある場合、Publicとの違いがないように思えるのですが。

    初歩的なことだとは思うのですが、どうかよろしくお願いいたします。

    2007年2月12日 11:09
  •  TI-cb400s さんからの引用
    他のホームページなどでクラスについて書かれているものがあったので一通り目を通したのですが、クラスと標準モジュールにPublicで作成したプログラムとの違いと、先の返答の例で書かれていた、患者用と職員用のデータアクセスを行うクラスを作りたい場合はDataAccessクラスを2つ作る必要があるのか、それとも、DataAccessというクラスひとつで対応が可能なのかという2点です。

    簡単に言ってしまうとクラスにはインスタンスがあるということです。
    そして標準モジュールを使用した場合にはインスタンスはありません。
    インスタンスに対して操作を行うという考え方が理解できればスッキリしてくるのではないでしょうか。

    「オブジェクト指向入門」などをキーワードにして検索してみれば
    より理解を深められる記事が見つかるかもしれません。

    患者用と職員用については、それぞれデータアクセスする時の DataAccess クラスの役割について考えてみてください。
    一つの DataAccess クラスで患者情報も職員情報もその他の情報も全部扱うのと、
    患者の情報を扱うのであれば、患者の情報だけを扱うクラス。名前は「患者DataAccess」など。
    職員の情報を扱うのであれば、職員の情報だけを扱うクラス。名前は「職員DataAccess」など。
    のようにした方が何をするクラスなのかが明確になりますし保守も楽になると思います。

     TI-cb400s さんからの引用
    もし、DataAccessというクラスをデータ取得別にいくつも作成をする必要がある場合、Publicとの違いがないように思えるのですが。

    コードだけ見てもあまり変化が見られないかもしれませんが、考え方に大きな違いがあります。

    2007年2月12日 12:58
  • おはようございます。

    次に勉強すべきことがはっきりとしてきました。

    まずは、勉強と平行して、実際にクラスを作成してみていろいろと試していきたいと思います。

    最後にひとつだけ質問ですが、クラスを作成する際に、「Fill」や「Update」といったものを使用しても大丈夫なのでしょうか。

    2007年2月12日 23:38
  • おはようございます。

     TI-cb400s さんからの引用
    次に勉強すべきことがはっきりとしてきました。

    まずは、勉強と平行して、実際にクラスを作成してみていろいろと試していきたいと思います。

    経験されることが一番自分の力に成ると思いますので、
    がんばってください。

     TI-cb400s さんからの引用
    最後にひとつだけ質問ですが、クラスを作成する際に、「Fill」や「Update」といったものを使用しても大丈夫なのでしょうか。

    これはどういう意味でしょうか。
    Public で宣言した同じ名称のメソッドが二つあるとまずいのではということでしょうか。
    ということであれば、問題ありません。

    クラス内のメソッドなりメンバはクラス内で閉じたものです。
    クラスの外で何が宣言されていようが関係ありません。
    このようにクラス内で閉じた世界を作れるのがクラスのいいところの一つですね。

    こういう細かな仕様について MSDN に記載されてありますので、
    ぜひ参照してみてください。

    2007年2月13日 0:08
  • ご回答ありがとうございます。

    少しずつしか進めないとは思いますが、がんばってみたいと思います。

    又、困ったときはよろしくお願い致します。

    本当にありがとうございました。

    2007年2月13日 2:01