Rat gesucht. Grid Bindingsource

02/07/2008 - 09:39 von Peter Haus | Report spam
Hallo

Ich verstehe das Problem leider nicht.


Zum nachvollziehen des Problems, habe ich mit der Northwind Datenbank
mittels Designer einen DataSet erstellt mit den Tabellen
Customers und Orders.
Aus dem Datenquellen Fenster habe ich die Customers Tabelle auf
die Form gezogen und danach die Detail Tabelle Orders (beide als Grid).
Noch zusàtzlich einen Button, zum auslössen des Filters.
Der Code aus Form1 ist unten.
Ich benutze VS2005.

Wenn ich jetzt das Programm laufen lasse, ist zb. CustomersID ALFKI
selektiert.
Ich klicke Button1 ( OrdersBindingSource.Filter = "EmployeeID = '4'" )
Im Orders Grid sind danach noch zwei Zeilen zu sehen.
Wenn ich irgendwo, im Orders Grid etwas àndere und in
die andere Zeile wechsel, kommt eine Exeption
"Der Index 2 hat keinen Wert.".
(Setze Breakpoint auf Beep in OrdersDataGridView_DataError().)
Dieser Fehler kommt nur dann, wenn ich im Event
OrdersBindingSource_ListChanged() auf die
Parent Row (Customers) zugreife, um in dieser etwas zu àndern.
(rowCust.CompanyName &= " X")



Kann mir jemand weiter helfen?
Wo ist der Fehler?
Bzw. wo kann ich Berechnungen durführen (zB.Summe aus Detail Rows),
die ich in einem Feld der Master Tabelle direkt anzeige?

Gruss Peter



Public Class Form1

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Me.OrdersTableAdapter.Fill(Me.NorthwindDataSet.Orders)
Me.CustomersTableAdapter.Fill(Me.NorthwindDataSet.Customers)

End Sub


Private Sub OrdersBindingSource_ListChanged(ByVal sender As Object,
ByVal e As System.ComponentModel.ListChangedEventArgs) Handles
OrdersBindingSource.ListChanged
Dim i As Integer
Dim rowOrd As NorthwindDataSet.OrdersRow
Dim rowCust As NorthwindDataSet.CustomersRow
Dim drv As DataRowView

If e.ListChangedType System.ComponentModel.ListChangedType.ItemChanged Or _
e.ListChangedType System.ComponentModel.ListChangedType.ItemAdded Or _
e.ListChangedType System.ComponentModel.ListChangedType.ItemDeleted Then
Try
drv = OrdersBindingSource.Current
If drv IsNot Nothing Then
rowOrd = drv.Row
rowCust = rowOrd.GetParentRow("FK_Orders_Customers")
rowCust.CompanyName &= " X"
End If
Catch ex As Exception
MessageBox.Show(ex.ToString)
End Try

End If
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
OrdersBindingSource.Filter = "EmployeeID = '4'"
End Sub

Private Sub OrdersBindingSource_DataError(ByVal sender As Object, ByVal
e As System.Windows.Forms.BindingManagerDataErrorEventArgs) Handles
OrdersBindingSource.DataError
Dim s As String

s = e.Exception.Message
Beep()
End Sub

Private Sub OrdersDataGridView_DataError(ByVal sender As Object, ByVal e
As System.Windows.Forms.DataGridViewDataErrorEventArgs) Handles
OrdersDataGridView.DataError
Dim s As String

s = e.Exception.Message
Beep() ' hier Breakpoint
End Sub
End Class
 

Lesen sie die antworten

#1 Peter Götz
02/07/2008 - 15:08 | Warnen spam
Hallo Peter,

so ganz habe ich immer noch nicht verstanden,
was Du da eigentlich machen willst. Aber schau
Dir mal das nachfolgende Beispiel an.

' /// Code in einer leeren Form
Public Class Form1
Private WithEvents DGVmaster As DataGridView
Private WithEvents DGVdetail As DataGridView

Private mDS As DataSet
Private mDTmaster As DataTable
Private WithEvents mDVmaster As DataView

Private mDTdetail As DataTable
Private WithEvents mDVdetail As DataView

Private WithEvents mCMmaster As CurrencyManager
Private WithEvents mCMdetail As CurrencyManager

Private Sub Form1_Load _
(ByVal sender As System.Object, _
ByVal e As System.EventArgs _
) Handles MyBase.Load

Me.Size = New Size(300, 430)
CreateControls()

CreateData()

DGVmaster.DataSource = mDVmaster
DGVmaster.AutoResizeColumns()

mCMmaster.Position = mCMmaster.Count - 1

DGVmaster.Columns(0).ReadOnly = True
DGVmaster.Columns(1).ReadOnly = True
End Sub


Private Sub CreateControls()
DGVmaster = New DataGridView
With DGVmaster
.SetBounds _
(10, 10, _
Me.ClientSize.Width - 20, _
Me.ClientSize.Height \ 2 - 5)

.Anchor = AnchorStyles.Left Or _
AnchorStyles.Top Or _
AnchorStyles.Right

.DefaultCellStyle.Font = _
New Font("Arial", 12)

.ColumnHeadersDefaultCellStyle.Font = _
New Font("Arial", 8, FontStyle.Bold)
End With
Me.Controls.Add(DGVmaster)

DGVdetail = New DataGridView
With DGVdetail
.SetBounds _
(10, _
DGVmaster.Bottom + 10, _
DGVmaster.Width, _
Me.ClientSize.Height - DGVmaster.Bottom - 20)

.Anchor = AnchorStyles.Left Or AnchorStyles.Right

.DefaultCellStyle.Font = _
DGVmaster.DefaultCellStyle.Font

.ColumnHeadersDefaultCellStyle.Font = _
DGVmaster.ColumnHeadersDefaultCellStyle.Font
End With
Me.Controls.Add(DGVdetail)

End Sub

Private Sub CreateData()
Dim i As Integer
Dim k As Integer
Dim DRm As DataRow
Dim DRd As DataRow
Dim Rnd As New Random

Dim ColsM() As DataColumn
Dim ColsD() As DataColumn

mDTmaster = New DataTable
With mDTmaster
.Columns.Add("ID", GetType(Integer))
.Columns(0).AutoIncrement = True
.Columns(0).AutoIncrementSeed = 1
.Columns(0).AutoIncrementStep = 1

.Columns.Add("Summe", GetType(Integer))

ColsM = New DataColumn() {.Columns(0)}
.Constraints.Add("pkID", ColsM, True)
End With

mDTdetail = New DataTable
With mDTdetail
.Columns.Add("mID", GetType(Integer))
.Columns.Add("dID", GetType(Integer))

.Columns.Add("Betrag", GetType(Integer))

ColsD = New DataColumn() {.Columns(0), .Columns(1)}
.Constraints.Add("pkIDmd", ColsD, True)
End With

Dim S As Integer
For i = 1 To 5
DRm = mDTmaster.NewRow
DRm.Item(0) = i
mDTmaster.Rows.Add(DRm)

S = 0
Dim Betrag As Integer
For k = 1 To Rnd.Next(2, 7)
DRd = mDTdetail.NewRow
With DRd
.Item(0) = i
.Item(1) = k
Betrag = Rnd.Next(100, 500)
.Item(2) = Betrag
S += Betrag
End With
mDTdetail.Rows.Add(DRd)
Next
DRm.Item(1) = S
Next

mDVmaster = New DataView(mDTmaster)

mCMmaster = _
DirectCast(Me.BindingContext(mDVmaster), _
CurrencyManager)

mDS = New DataSet
mDS.Tables.Add(mDTmaster)
mDS.Tables.Add(mDTdetail)

Dim Rel As New DataRelation _
("RelMasterDetail", _
mDTmaster.Columns(0), _
mDTdetail.Columns(0))

mDS.Relations.Add(Rel)

AddHandler _
mCMmaster.PositionChanged, _
AddressOf mCMmaster_PositionChanged
End Sub


Private Sub Form1_Resize _
(ByVal sender As Object, _
ByVal e As System.EventArgs _
) Handles Me.Resize

If DGVmaster IsNot Nothing Then
DGVmaster.Height = Me.ClientSize.Height \ 2 - 15

DGVdetail.Top = DGVmaster.Bottom + 10
DGVdetail.Height = DGVmaster.Height
End If
End Sub

Private Sub mCMmaster_PositionChanged _
(ByVal sender As Object, _
ByVal e As System.EventArgs)

If mCMmaster.Position > -1 Then
' neue DetailView mit zugehörigem
' CurrencyManager erstellen
Dim DRV As DataRowView
DRV = DirectCast(mCMmaster.Current, DataRowView)
mDVdetail = DRV.CreateChildView(mDS.Relations(0))

mCMdetail = _
DirectCast(Me.BindingContext(mDVdetail), _
CurrencyManager)

' neue DetailView an DGVdetail binden
DGVdetail.DataSource = mDVdetail

DGVdetail.Columns(0).ReadOnly = True
DGVdetail.Columns(1).ReadOnly = True
DGVdetail.AutoResizeColumns()
End If
End Sub

Private Sub mDVdetail_ListChanged _
(ByVal sender As Object, _
ByVal e As System.ComponentModel.ListChangedEventArgs _
) Handles mDVdetail.ListChanged

If e.ListChangedType = _
System.ComponentModel.ListChangedType.ItemAdded Then
' neue dID für neuen Detaildatensatz erstellen
Dim NumRows As Integer = mDVdetail.Count
mDVdetail.Item(NumRows - 1).Item(1) = NumRows
End If

Dim i As Integer
Dim S As Integer
Dim DRV As DataRowView
Dim Betrag As Integer
For i = 0 To mDVdetail.Count - 1
DRV = mDVdetail.Item(i)
If DRV.Item(2) Is DBNull.Value Then
Betrag = 0
Else
Betrag = DirectCast(DRV.Item(2), Integer)
End If
S += Betrag
Next
DirectCast(mCMmaster.Current, DataRowView).Row.Item(1) = S
End Sub


Private Sub DGVmaster_CellValidating _
(ByVal sender As Object, _
ByVal e As DataGridViewCellValidatingEventArgs _
) Handles DGVmaster.CellValidating

Dim DRV As DataRowView
DRV = DirectCast(mCMmaster.Current, DataRowView)
If DRV.IsNew Then
mCMmaster.EndCurrentEdit()
End If
End Sub
End Class
' \\\ E N T E

Nach dem Programmstart
kannst Du in der unteren DetailTabelle nur die Werte
in der Spalte Betrag àndern. Mit der Übernahme einer
solchen Änderung (z.B. Datensatzwechsel) wird die
Summe aller Betràge für diese "mID" in der oberen
MasterTabelle im Feld Summe angezeigt.

Ich rate mal, dass es in etwa das ist, was Du
machen möchtest.

Gruß aus St.Georgen
Peter Götz
www.gssg.de (mit VB-Tipps u. Beispielprogrammen)

Ähnliche fragen