I have a table, SampleData, that has a child table, Measurements. On my WinForm, frmMain, a single SampleData object is bound to the SampleDataBindingSource; the MeasurementsBindingSource has SampleDataBindingSource as its datasource and Measurements as its DataMember. A set of textboxes are bound to SampleDataBindingSource; a datagridview is bound to MeasurementsBindingSource.
For frmMain, I also have a presenter class, preMain, which contains a property, CurrentSample, of type SampleData. The SampleDataBindingSource.DataSource
is bound to the CurrentSample property of preMain.
When enough of the properties in Measurements have been assigned, it calculates the FiringFactor and, if the FiringFactor is not 1, it adds another Measurement item to the CurrentSample's Measurement entityset:
Partial Class Measurement
Private Sub UpdateFiringFactor()
Dim necessaryDataIsAvailable As Boolean = (Me.CrucibleMass IsNot Nothing And _
Me.CrucibleSampleFiredMass IsNot Nothing And _
Me.CrucibleSampleMass IsNot Nothing)
If necessaryDataIsAvailable Then
Me.FiringFactor = CDbl((Me.CrucibleSampleFiredMass - Me.CrucibleMass) / (Me.CrucibleSampleMass - Me.CrucibleMass))
If Me.FiringFactor <> 1 Then
Me.SampleData.AddNewMeasurement()
End If
End If
End Sub
Private Sub OnCrucibleMassChanged()
UpdateFiringFactor()
End Sub
Private Sub OnCrucibleSampleFiredMassChanged()
UpdateFiringFactor()
End Sub
Private Sub OnCrucibleSampleMassChanged()
UpdateFiringFactor()
End Sub
End Class
When I enter values for CrucibleMass, CrucibleSampleMass, and CrucibleSampleFiredMass in the datagridview, the UpdateFiringFactor method does run correctly and I eventually get another Measurement item added to CurrentSample's Measurements entityset. However, the datagridview does not show a new row and the MeasurementsBindingSource only has 1 record (but CurrentSample.Measurements.Count = 2
).
Why does the change in CurrentSample.Measurements
not propogate to MeasurementsBindingSource
? I have tried MeasurementsBindingSource.ResetBindings(False)
, MeasurementsDataGridView.Refresh
, SampleDataBindingSource.ResetBindings(False)
, but nothing seems to update MeasurementsBindingSource
or its datagridview.
Here's the solution I found to the entityset/bindingsource problem:
Imports System.ComponentModel
Partial Class Measurement
Public Sub ChangeCrucibleMass(ByVal thisMass As Double)
CrucibleMass = thisMass
UpdateFiringFactor()
End Sub
Public Sub ChangeCrucibleSampleMass(ByVal thisMass As Double)
CrucibleSampleMass = thisMass
UpdateFiringFactor()
End Sub
Public Sub ChangeCrucibleSampleFiredMass(ByVal thisMass As Double)
CrucibleSampleFiredMass = thisMass
UpdateFiringFactor()
End Sub
Private Sub UpdateFiringFactor()
If AllDataAreAvailable() Then
FiringFactor = (CrucibleSampleFiredMass - CrucibleMass) / (CrucibleSampleMass - CrucibleMass)
Me.Sample.OnMeasurementsChanged(Nothing, Nothing)
End If
End Sub
Private Function AllDataAreAvailable() As Boolean
AllDataAreAvailable = False
Dim allFieldsHaveValue As Boolean = (CrucibleMass IsNot Nothing And CrucibleSampleFiredMass IsNot Nothing And CrucibleSampleMass IsNot Nothing)
If allFieldsHaveValue Then
Dim denominatorIsNotZero As Boolean = (CrucibleSampleMass - CrucibleMass) <> 0
Return denominatorIsNotZero
End If
End Function
End Class
Partial Class Sample
Public Sub OnMeasurementsChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Handles Me.PropertyChanged
If Me.Measurements.Count > 0 AndAlso Me.Measurements.Last.FiringFactor IsNot Nothing AndAlso Me.Measurements.Last.FiringFactor <> 1 Then
Me.Measurements.Add(New Measurement With {.CrucibleMass = Me.Measurements.Last.CrucibleMass})
RaiseEvent RefreshMeasurementsBinding()
End If
End Sub
Private Sub OnCreated()
Me.Measurements.Add(New Measurement)
End Sub
Public Event RefreshMeasurementsBinding()
End Class
Here's a screenshot of the form:
And the code-behind:
Imports System.ComponentModel
Public Class Form1
Private WithEvents newSample As Sample
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
newSample = SampleConduit.GetSample(1)
'newSample = New Sample
Me.SampleBindingSource.DataSource = newSample
OnRefreshMeasurementsBinding()
End Sub
Private Sub OnRefreshMeasurementsBinding() Handles newSample.RefreshMeasurementsBinding
Me.MeasurementsBindingSource.DataSource = newSample.Measurements.GetNewBindingList
End Sub
Private Sub MeasurmentsDataGridView_CellClick(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles MeasurmentsDataGridView.CellClick
Me.MeasurementsBindingSource.EndEdit()
Dim currentMeasurement = CType(Me.MeasurementsBindingSource.Current, Measurement)
Select Case e.ColumnIndex
Case 0
currentMeasurement.ChangeCrucibleMass(GetMeasurement)
Case 1
currentMeasurement.ChangeCrucibleSampleMass(GetMeasurement)
Case 2
currentMeasurement.ChangeCrucibleSampleFiredMass(GetMeasurement)
End Select
End Sub
Private Function GetMeasurement() As Double
Return CDbl(InputBox("Measurement:", "Get Measurement", "0"))
End Function
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSave.Click
Dim currentSample = CType(Me.SampleBindingSource.Current, Sample)
SampleConduit.SaveSample(currentSample)
End Sub
End Class
The solution hinges on the RefreshMeasurementsBinding event in the Sample class and the OnRefreshMeasurementsBinding method in the form. Frequently setting the MeasurementsBindingSource to the GetNewBindingList method on the Measurements entityset seems a bit kludgy, but it works.
See Item#3 about EntitySets and BindingSource and GetNewBindingList in this forum posting:
http://www.infragistics.com/community/forums/t/43526.aspx