none
BindingSourceのPositionプロパティについて RRS feed

  • 質問

  • はじめまして、秋月と申します。

    DataGridViewについて少々分からないことがあり

    書込みさせて頂きました。

    データソースウィンドウからDataGridViewコントロールと

    詳細コントロールをフォームに配置しました。

    フォーム上側には詳細コンロトール、下側にはDataGridViewコントロール

    という感じです。

    DataGridViewの1レコードを選択すれば、上側の詳細コントロールに

    選択したレコードの詳細が表示されます。

    この動作を逆に、キーとなるコードを詳細コントロールの方で入力したら

    既存コードであれば、そのレコードを選択したような動作

    また、新規コードであればBindingNavigatorの「新規追加」ボタンの

    ような動作としたいのですが、どうすればよいのでしょうか。

    BindingSourceのPositionプロパティを変更すればうまく動作する

    ような気がしたのですが、Positionプロパティにセットする値を

    どのように取得していいか分かりません。

    foundRowsになにかヒントがないものかとプログラムの実行中に

    クイックウォッチウィンドウで調べていたら

    Form1.m_Const.foundRows(0).rowIDという項目がありました。

    選択したレコードのrowIDのようでしたので、これをPositionに

    セットすればと思ったのですが、

    「rowIDはSystem.Data.DataRowのメンバではありません」と

    エラーになってしまいました。

    説明が不十分で申し訳ありませんが、アドバイスを宜しくお願い致します。

    Private Sub コード_Leave(ByVal sender As Object....

        If Trim(Me.コード.Text) <> "" Then
            '入力値の書式を設定する
            Me.コード.Text = Format(CInt(Me.コード.Text), fmtコード)
            '入力されたコードの存在チェック
            foundRows = Me.ds.TableA.Select("コード = '" & Me.コード.Text & "'")
            If foundRows.Length > 0 Then
                '既存コード
                lblStatusBar.Text = ""
                'BindingSourceのPositonを変更
                'Me.bs.Position = Form1.m_Const.foundRows(0).rowID - 1 ←エラー
            Else
                '新規コード
                lblStatusBar.Text = "新規レコードです。"
                bs.AddNew()
            End If
        End If

    End Sub

    OS Win2K SP4

    環境 VS2005(.Net Framework Ver 2.0)

    言語 VB.NET

    タイプ Windowsフォーム

    2006年11月16日 6:42

すべての返信

  • こんな形で取れませんか?

    Dim fi As FieldInfo = GetType(DataRow).GetField("rowID", BindingFlags.NonPublic Or BindingFlags.Instance)
    Dim rowID As Integer = CType(fi.GetValue(foundRows(0)), Integer)
    2006年11月16日 9:23
    モデレータ
  • rowIDをPositionにセットしてもうまくいかないです。
    BindingSourceが管理しているDataViewからデータをもらわなければいけません。
    以下のように検索してPositionにセットしてください。
    DataViewのFindメソッドで可能ならそっちのほうが手間いらずです。


        Dim view As DataView = CType(Me.BindingSource.List, DataView)
        'Dim index As Integer = view.Find(key)
        Dim index As Integer = Find(view, key, "コード")
        Me.BindingSource.Position = index
     
        Public Function Find(ByVal view As DataView, ByVal keyName As String, ByVal key As Object) As Integer
            Dim found As Boolean
            Dim rowIndex As Integer
            For rowIndex = 0 To view.Count - 1
                found = True
                If Not view(rowIndex)(keyName).Equals(key) Then
                    found = False
                    Exit For
                End If
                If found Then
                    Return rowIndex
                End If
            Next rowIndex
            Return -1
        End Function 'Find
    2006年11月16日 12:04
  • Findのコードが間違えてました。


        Public Function Find(ByVal view As DataView, ByVal keyName As String, ByVal key As Object) As Integer
            Dim rowIndex As Integer
            For rowIndex = 0 To view.Count - 1
                If view(rowIndex)(keyName).Equals(key) Then
                    Return rowIndex
                End If
            Next rowIndex
            Return -1
        End Function 'Find
    2006年11月16日 12:07
  •  trapemiya さんからの引用
    Dim fi As FieldInfo = GetType(DataRow).GetField("rowID", BindingFlags.NonPublic Or BindingFlags.Instance)

    あれっ? _rowIDに変わってるようですね。
    Dim fi As FieldInfo = GetType(DataRow).GetField("_rowID", BindingFlags.NonPublic Or BindingFlags.Instance)
    2006年11月16日 15:49
    モデレータ
  • こんにちは、秋月です。

    trapemiya様、えムナウ様、早速のアドバイスありがとうございます!!

    trapemiya様のアドバイス通り次の方法で行の特定は出来ました。

        Dim fi As Reflection.FieldInfo = _
            GetType(DataRow).GetField("_rowID", Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance)
        Dim rowID As Integer = CType(fi.GetValue(foundRows(0)), Integer)
        Me.bs.Position = rowID - 1

    また、えムナウ様のおっしゃる「rowIDをセットしてもうまく動作しない」を参考に

    次のようなコートで解決致しました。

    If Trim(Me.コード.Text) <> "" Then
        '入力値の書式を設定する
        Me.コード.Text = Format(CInt(Me.コード.Text), fmtコード)
        Dim dv As DataView = CType(Me.bs.List, DataView)
        '入力されたコードの存在チェック(有り:行番号 無し:-1)
        Dim Index As Integer = Find(dv, "コード", Me.コード.Text)
        'BindingSourceのPositonを変更
        Me.bs.Position = Index
        'メッセージを設定する
        If Index = -1 Then
            '新規コード
            lblStatusBar.Text = "新規レコードです。"
            bs.AddNew()
        Else
            '既存コード
            lblStatusBar.Text = ""
        End If
    End If

    Private Function Find(ByVal dv As DataView, ByVal KeyName As String, ByVal Key As Object) As Integer
        For RowIndex As Integer = 0 To dv.Count - 1
            If dv(RowIndex)(KeyName).Equals(Key) Then
                Return RowIndex
            End If
        Next
        Return -1
    End Function

    2006年11月17日 4:09
  •  秋月 さんからの引用

    また、えムナウ様のおっしゃる「rowIDをセットしてもうまく動作しない」を参考に

    このスレを読んだ人がわかりにくい場合があると思いますので、なぜうまく動作しないのか補足しておきます。

    うまく動作しないのは、DataGridViewでソートが行われている場合です。この場合、rowIDは必ずしも行の先頭から昇順になっていません。つまり、検索結果で見つけた行のrowIDが5だからといって、かならずしもCurrencyManagerのPositionが5番目とは限らなくなるからです。逆に言えば、DataGridViewでソートが行われていなければ、うまくいきます。

    2006年11月17日 4:30
    モデレータ
  • >DataGridViewでソートが行われている場合です。
    BindingSource.Filter プロパティ や BindingSource.Sort プロパティ を使っている場合、
    DataGridView.Sort メソッドを使った場合、
    UIでカラムヘッダーをクリックしてソートした場合、

    いろんなケースが考えられますね。

    いずれにしろDataGridViewやBindingSourceを使っている時点で使える局面が限られてきますのでrowIDはまずいんじゃないでしょうか。

    2006年11月17日 5:42
  • 秋月です。

    trapemiya様、えムナウ様、分かり易い解説ありがとうごさいます。

    現在はDataGridViewでソートを行っているわけではありませんが

    今後、ソートをする機会もあると思います。

    解説して頂いて本当に助かりました!

    2006年11月17日 6:48