DataRepeaterに関して

解決


misamisa  2012-11-05 13:28:26  No: 147946  IP: [192.*.*.*]

開発環境:Visual Basic 2008

教えて頂きたいと思います。

現在、DataRepeater  にAとBという2つのテキストが配置してあり、ある行のAテキストをダブルクリック
した場合、別ウィンドから選択された値をBテキストに代入するような事を考えています。

DataGridView等でカレント行というは理解できますが、このDataRepeater でのカレント行の取得という
のはどのような形ですれば良いでしょうか?

また、DataRepeaterの中に配置してあるテキストボックスをダブルクリックというのは、そもそも認識できる
のでしょうか?

教えて下さい。

よろしくお願いします。

編集 削除
オショウ  2012-11-05 14:43:35  No: 147947  IP: [192.*.*.*]

カレントは取得できますし、ダブルクリックにも反応します。
ちゃんとメンバに定義されてます。
イベントが起きないのかプログラムの仕方が解らないのか、
どちら?

VB 2008 と言うことなので、コントロールを配置して、イベン
ト定義を探すなり、ダブルクリックしてみるなり・・・探す方
法はいろいろあると思いますが。

以上。

編集 削除
shu  2012-11-05 15:30:57  No: 147948  IP: [192.*.*.*]

サンプル:
    Private Sub TextBox1_DoubleClick(sender As Object, e As System.EventArgs) Handles TextBox1.DoubleClick
        Dim row = DirectCast(BindingSource1.Current, DataRowView).Row
        Dim Text2 = DataRepeater1.CurrentItem.Controls("TextBox2")
        Text2.Text = row("Column1").ToString
    End Sub

編集 削除
misamisa  2012-11-05 15:59:09  No: 147949  IP: [192.*.*.*]

shu様、ご回答ありがとうございます。

サンプルまで記載して頂き、本当にありがとうございます。

初歩的な質問で申し訳ありません。

>Dim row = DirectCast(BindingSource1.Current, DataRowView).Row

上記のBindingSource1 というのは何を指しているのでしょうか、、、

教えて下さい。

編集 削除
shu  2012-11-05 17:51:57  No: 147950  IP: [192.*.*.*]

> 上記のBindingSource1 というのは何を指しているのでしょうか、、、
BindingSourceを通してデータ連結を行っている前提です。
BindingSourceを使用するとDataRepeater上のCurrentが変わると
BindingSourceのCurrentも変わります。
どのようにデータ連結を行っていますか?
こちらの提示した内容がどの位使えるのかは分かりません。
まず試したことを提示された方がよいかと思います。

編集 削除
misamisa  2012-11-06 08:52:33  No: 147951  IP: [192.*.*.*]

shu様、ご回答ありがとうございます。

ご指摘がありました連結の仕方に関してですが、以下のように起動時にデータベースを検索し、その
内容を連結しています。

その後、Datarepeater上にある品目番号というテキストをダブルクリックするという処理になります。

教えて頂いたように、TXT_品目番号_DoubleClick の処理の中に記載しましたが、BindingSource1が何に該当
するかわからず、、、

何かから何まで質問する形で申し訳ありません。

教えて下さい。


    Private Sub 仕様書_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        'データセットにテーブルを追加する
        dtTable = dtSet.Tables.Add("品目マスタ検索_TBL")
        'テーブルにフィールドを追加する
        '.Add("フィールド名", フィールドの型)で追加します
        dtTable.Columns.Add("品目番号", Type.GetType("System.String"))
        dtTable.Columns.Add("品目名称", Type.GetType("System.String"))
        dtTable.Columns.Add("メーカー名", Type.GetType("System.String"))

        Dim Connection As New OracleConnection
        Dim Command As New OracleCommand

        Try

            'Oracleへのコネクションの確立
            Connection.ConnectionString = "User Id=XXXXXX; Password=999999; Data Source=XE"

            Command.Connection = Connection

            Try

                Dim Select_SQL As String

                'SQL文作成
                Select_SQL = "SELECT * FROM T_品目マスタ"

                Dim adp As New OracleDataAdapter(Select_SQL, Connection)

                ds.Clear()

                'データセットの中に仕入先マスタ_Tというテーブルを作成し、そこへ格納する。
                adp.Fill(ds, "品目マスタ_T")

                'テーブルを指定
                DP_仕様書.DataMember = "品目マスタ_T"

                'コントロールにデータを連結
                TXT_品目番号.DataBindings.Add("Text", dt, "品目番号")
                TXT_仕様書型名.DataBindings.Add("Text", dt, "品目名称")
                TXT_部品表型名.DataBindings.Add("Text", dt, "社外名称")
                TXT_メーカー名.DataBindings.Add("Text", dt, "メーカー名")

                'データセットをDataGridViewにバインド
                DP_仕様書.DataSource = ds

            Catch ex As Exception
                ' 例外が発生した時の処理

                MsgBox(ex.Message)

            End Try

        Catch ex As Exception


        End Try

        '新規行を作成
        DP_仕様書.AddNew()

    End Sub



   Private Sub TXT_品目番号_DoubleClick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TXT_品目番号.DoubleClick

        Dim IN_品目番号 As String


        Dim row = DirectCast(BindingSource1.Current, DataRowView).Row
        Dim Text2 = DP_仕様書.CurrentItem.Controls("TXT_品目番号")
        Text2.Text = row("品目番号").ToString



   End Sub

編集 削除
shu  2012-11-06 11:06:22  No: 147952  IP: [192.*.*.*]

FormデザインでBindingSourceをツールボックスより貼り付けて

DP_仕様書.DataMember => BindingSource1.DataMember
DP_仕様書.DataSource => BindingSource1.DataSource
〜DataBindings〜(〜dt〜) => dtをBindingSource1
DP_仕様書.DataSource = BindingSource1を追加
とすれば
BindingSource経由になります。各記述箇所は調整して下さい。

編集 削除
misamisa  2012-11-07 10:26:08  No: 147953  IP: [192.*.*.*]

shu様、ご回答ありがとうございます。

>FormデザインでBindingSourceをツールボックスより貼り付けて

頭が悪く、ここまでは理解できましたが、教えて頂いたそれ以下の記述を
どこにどのように書けば良いのかわかりません、、、

>DP_仕様書.DataMember => BindingSource1.DataMember
>DP_仕様書.DataSource => BindingSource1.DataSource
>〜DataBindings〜(〜dt〜) => dtをBindingSource1
>DP_仕様書.DataSource = BindingSource1を追加

また、

>〜DataBindings〜(〜dt〜) => dtをBindingSource1

これも良くわからず、、、

本当に申し訳ありません。

教えて下さい。

編集 削除
魔界の仮面弁士  2012-11-07 12:54:38  No: 147954  IP: [192.*.*.*]

DataRepeater を使わない状態で、フォーム上のテキストボックスに対して、
  TextBox1.DataBindings.Add("Text", dtTable, "品目名称")
のようにすると、TextBox1.Text に対してデータが表示されますよね。

このデータテーブルをさらに、フォーム上の DataGridView に対して、
  DataGridView1.DataSource = dtTable
のようにすると、データテーブルの中身が DataGridView に表示されます。

TextBox は複数レコードを表示できませんが、DataGridView 側で
選択行を変えると、TextBox 側の表示も、その行の内容に差し替わります。

さらに DataRepeater も併用している場合は、DataGridView の選択行と
DataRepeater の選択行と、フォーム上の TextBox が表示している行とが、
それぞれ連動することになります。


ここまではよろしいでしょうか。


さて、そうすると
  ・DataGridView や DataRepeater 無しで TextBox だけの場合、
    どうやって『現在の行』を移動させればよいのか?
  ・DataRepeater 等で、『現在の行』を調べるにはどうすれば良いのか?
といった問題が生じてくるかと思います。


実は、この「現在の行」を管理するためのオブジェクトが存在しています。
そしてそのオブジェクトには、
  Dim man As BindingManagerBase = TextBox1.BindingContext(oDataTable)
のようにしてアクセスできます。このオブジェクトが肝となります。

DataGridView や DataRepeater でも、同様にして管理オブジェクトを
取得できますし、フォームからも
  Dim man As CurrencyManager = Me.BindingContext(oDataTable)
として取得できます。(CurrencyManager は BindingManagerBase を継承しています)


このオブジェクトには .Position プロパティがあり、これが現在の行番号(0 以上)を示しています。
このプロパティを変更すれば、現在見ているレコードも変更されるという寸法です。
(DataRepeater の CurrentItemIndex プロパティと同じ機能です)


また、BindingManagerBase の .Current プロパティからは DataRowView クラスが返されるので、
  Dim rowView As DataRowView = DirectCast(man.Current, DataRowView)
  Dim row As DataRow = rowView.Row
のようにして、バインド元の DataRow にアクセスすることもできます。

これを使う事で、DataRepeater 等でのカレント行の取得が可能になります。


----------------------
また、shu さんが紹介された BindingSource は、この管理情報を内包した中継器に当たります。


ツールバーから、BindingSource をフォームに貼り、BindingSource1 を
用意しておきます。そして、データバインドの設定を
  DataGridView1.DataSource = dtTable 
  TextBox1.DataBindings.Add("Text", dtTable , "品目番号")
  TextBox2.DataBindings.Add("Text", dtTable , "品目名称")
  DataRepeater1.DataSource = dtTable 
から、以下のように変更します。

  BindingSource1.DataSource = dtTable
  DataGridView1.DataSource = BindingSource1
  TextBox1.DataBindings.Add("Text", BindingSource1, "品目番号")
  TextBox2.DataBindings.Add("Text", BindingSource1, "品目名称")
  DataRepeater1.DataSource = BindingSource1

対象コントロール(データコンシューマー)と DataSet/DataTable の間に、
BindingSource が中継される形となりますが、こうすると、『現在行』の管理を
この BindingSource のメンバーを通じて行えるようになります。


BindingSource を経由される事には、幾つかの利点があります。


一つは、「現在の行」にアクセスするのが簡単になるという点。
BindingSource があれば、わざわざ BindingManagerBase を再取得せずとも、
  BindingSource1.Position プロパティ
  BindingSource1.Current プロパティ
  BindingSource1.MoveFirst() / .MoveNext() / .MovePrevious() / .MoveLast() メソッド
  BindingSource1.AddNew() メソッド
などを利用できるため、現在行の管理が容易になります。
(BindingSource1.CurrencyManager から、BindingManagerBase を得ることもできます)


もう一つは、フィルタリングやソート機能を有している点。
  BindingSource1.Filter = "品目名称 LIKE '%ab%'"
  BindingSource1.Sort = "品目番号 DESC"
のようにして、SQL の WHERE や ORDER BY 相当の実装が行えます。DataView にも同じ機能がありますね。
(DataTable を直接割り当てた場合は、dtTable.DefaultView から既定の DataView を得られます)


さらにもう一つ。DataSet/DataTable のインスタンスを作り直した場合に
再バインドするのが容易になるというメリットもあります。

もし、元の様に DataSet/DataTable に直接バインドさせていた場合、
DataSet/DataTable そのものを作り直したような場合においては、
(DataTable の中身を入れ替えるのではなく、インスタンス自体を再生成する場合)
  DataGridView1.DataSource = oDataTable
  DataRepeater1.DataSource = oDataTable
などのように、個々のコントロールのバインド(DataSource/DataBindings)を
やり直さなければなりませんが、BindingSource を中継させていれば、
  BindingSource1.DataSource = oDataTable
という一行を再実行するだけで済むわけです。個々のコントロールは
BindingSource1 を参照したままなので、再設定は不要となります。

編集 削除
misamisa  2012-11-07 15:57:45  No: 147955  IP: [192.*.*.*]

shu様、魔界の仮面弁士様、ご回答ありがとうございました。

ようやく内容を理解し、やりたい事が実現しました。

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

しかし、またもやひっかかり、、、、別であげさせて頂きました。

よろしくお願いします。

編集 削除