質問者
BindingSourceのPositionプロパティについて

質問
-
はじめまして、秋月と申します。
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 IfEnd Sub
OS Win2K SP4
環境 VS2005(.Net Framework Ver 2.0)
言語 VB.NET
タイプ Windowsフォーム
すべての返信
-
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 -
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 -
こんにちは、秋月です。
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 IfPrivate 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 -
秋月 さんからの引用
また、えムナウ様のおっしゃる「rowIDをセットしてもうまく動作しない」を参考に
このスレを読んだ人がわかりにくい場合があると思いますので、なぜうまく動作しないのか補足しておきます。うまく動作しないのは、DataGridViewでソートが行われている場合です。この場合、rowIDは必ずしも行の先頭から昇順になっていません。つまり、検索結果で見つけた行のrowIDが5だからといって、かならずしもCurrencyManagerのPositionが5番目とは限らなくなるからです。逆に言えば、DataGridViewでソートが行われていなければ、うまくいきます。