Link to home
Start Free TrialLog in
Avatar of newyuppie
newyuppieFlag for Ecuador

asked on

problem with binding object parse and format events

vb2005

hi, im having some problems handling the format and parse events of some textboxes.

this question i asked has the priors (https://www.experts-exchange.com/questions/21891973/One-Way-Data-Binding.html).
basically, i have a form with a bunch of textboxes. some of them are bound to the dataset, others aren't and are readonly and perform calculations based on the rest of the textboxes.
i now needed to send this computed readonly values back to the database (for sake of reporting), so the person whom i accepted the answer from in the linked question suggested i create a bindingobject for these readonly textboxes and handle its format and parse events.

so i did, created new columns for these values on the database, reconfigured the tableadapter, and created binding object which handle the format event, so that the value of the database gets replaced by the computed value when i fill the datatable (the end user never sees the database content, but a similar result computed by a defined function).

basically, the problem i am having now is that when i call tableadapter update command to send all the info back to the database, after its done all my readonly textboxes (the ones which i handled the format event) erase their values and place 0 instead (zero because their computed value are always arithmetic functions of the other textboxes).

why do you reckon this is happening? is it that after the update the format event of the bindings are not being called?
Avatar of Sancler
Sancler

Can you please show the code you are actually using in your app?  You refer to handling the format and parse events of the binding object but the code in the link you provided does not handle the parse event.  Also, I'm not sure I've grasped which controls are bound and which aren't.  If you use a read only textbox to perform (or at least show the result of) a calculation, and then send the result of that back to the database I assume that must be bound.  But where does the data on which those calculation/s are performed come from: the datatable and not displayed?  displayed in a bound control?  entered by the user?  or what?

Roger
Avatar of newyuppie

ASKER

Hi Roger, thanks for the answer. I hope i can clarify a bit:

for the sake of simplicity (i have over 50 textboxes in the form) lets assume there are 2 textboxes which are bound in the usual way to a dataset. These textboxes are read/write enabled, and user is supposed to enter in them values. of course when i update the datatable these 2 values also get stored (they are bound). so when i load the form these 3 textboxes pull the values from the datatable, but are still subject to user input.

Assume the 3rd textbox calculates de SUM of the other 2 textboxes. this 3rd textbox is read/only and user cannot enter values. it's .text property is updated automatically handling the _textchanged event of the other 2 textboxes to perform the calculation and display the result.

this was my scenario and everything worked fine. now, i need to add one more column to the dataset, to store the sum of the first 2 textboxes. so i need to calculate it via my function, and then when i .endedit the bindingsource it has to pass this sum to the database for storage. one more thing is that when i open the form and load the dataset, i want to display as usual the first 2 textboxes (reading the values stored), but the 3rd textbox i dont want to read the stored sum, but calculate it again. in sum, this 3rd texbox must be readonly to the user, and "write-only" to the database.

so in the code i provided on the link to, anyoneis gave me an example of code to handle format event of a new binding of the textbox. i made some modifications and here's what i have so far. i show code for only one binding (i have over 10 now).

assume the calculation for the 3rd readonly textbox comes from this sub:

Private Sub CalculateCapEnd()
        Dim TasaAnual As Double
        Dim TasaMensual As Double
        Dim Plazo As Integer
        Dim SaldoNeto, IngresoNeto, GastoMicro, GastoFamiliar As Double

        Double.TryParse(Me.TasaAnualTextBox.Text, TasaAnual)
        Integer.TryParse(Me.Plazo_Solicitado__en_meses_TextBox.Text, Plazo)
        Double.TryParse(Me.IngresoNetoTextBox.Text, IngresoNeto)
        Double.TryParse(Me.GastoMicroTotalTextBox.Text, GastoMicro)
        Double.TryParse(Me.GastoTotalFamiliarTextBox.Text, GastoFamiliar)

        SaldoNeto = IngresoNeto - GastoMicro - GastoFamiliar
        TasaMensual = TasaEfectivaMensual(TasaAnual)

        Me.CapEndTextBox.Text = CapEnd(TasaMensual, Plazo, SaldoNeto).ToString("F")
    End Sub

the previous sub gets called whenever user makes changes to the text on the first 2 texboxes (called in the _textchanged event handler)

i also added this code to bind the 3rd textbox (readonly textbox):

Private Sub Bind3rdTextbox()
        Dim _CapEnd As New Binding("Text", Me.SolicitantesBindingSource, "CapEnd", True)
        Me.CapEndTextBox.DataBindings.Add(_CapEnd)
        AddHandler _CapEnd.Format, AddressOf WriteCapEnd
End Sub

Private Sub WriteCapEnd(ByVal sender As System.Object, ByVal e As ConvertEventArgs)
        ' We want to ignore the current value, and instead compute it
        Try
            e.Value = CE.ToString
        Catch ex As Exception
            e.Value = Nothing
        End Try
End Sub

Private Function CE() As Double
        CalculateCapEnd()

        Dim CapEnd As Double
        Double.TryParse(Me.CapEndTextBox.Text, CapEnd)

        Return CapEnd
End Function


So, basically, the 3rd textbox has the _format event handled by the sub WriteCapEnd, which in turns uses the result of function CE which only purpose is to run sub CalculateCapEnd (which will in turn set the 3rd textbox .text property to the corresponding correct value) and return that value to the format event.

behaviour:
the real behaviour of all these subs is as following: i open the form and data gets loaded into textbox 1 and 2, and texbox 3 calculates its value (because i handle all of this in the Load event, i dont think its because of the _format event since this behaviour happened before i set to do this).
if i call bindingsource.endedit and tableadapter.update methods (save the data back to the form), what happens is that the value on the 3rd textbox is not saved in the database (1st and 2nd are). also, 3rd texbox .text resets to 0 no matter what value it was showing before the update was called.

if i close and reopen the form, i get all textboxes filled correctly again.

im sorry for the extension of all of this, i hope i could clarify the issue a bit.


I've not seen a Binding's .Format event used like this before.  It is normally used, as it says, to FORMAT the datatable's data for display purposes rather than to CREATE data for it.  That, however, is by the by.  I can see nothing wrong in principle with this approach although it is new to me.  Where it falls down in this case, however, is that it has no matching .Parse.  Have a look at this

http://msdn2.microsoft.com/en-us/library/system.windows.forms.binding.format.aspx

The code provided by anyoneis did say that it was providing a one-way binding, and the Console output on button1 illustrated that the newly calculated value in textbox3 did not get back to the datatable.  That being so, it would not get back to the database on an update.

With a matching .Parse on the lines explained in the link above such a calculated value would get back to the datatable.  So, if anyoneis' code was amplified by

        AddHandler sumBinding.Parse, AddressOf SaveSum

as well as

        AddHandler sumBinding.Format, AddressOf FormatSum

and

    Private Sub SaveSum(ByVal sender As System.Object, ByVal e As ConvertEventArgs)
        e.Value = ComputeSum()
    End Sub

it would, in theory, achieve what you want.  Unfortunately for your scenario that .Parse event is (so far as I know) only triggered if the user has altered the data in the control.  Here, as the textbox is readonly, that just can't happen.

So far, I've only addressed part of the problem - "the value on the 3rd textbox is not saved in the database" - but I think getting that right first is crucial.  Until the data is right, display issues are peripheral.

Looking at it from a data angle, rather than a display angle, can I ask why you are calculating figures in your app to pass back to a database when, I think, all the elements necessary for that calculation are in your database anyway?  What is your database?  Does it not have the ability to do calculations of this sort itself?

If you want to continue looking at this as a display problem, we may be able to get round the difficulty you are currently facing.  But my inclination would be to treat the calculation as something to be done at the database end and/or at the application end rather than trying to pass the result between the two.  x + y + z = the same whichever end it is done at.  And if you can do that, all these .Format and .Parse issues will just disappear.

Roger
thanks for your clarifications and comments. i can now see why you say that .Parse and .Format events are meant to manage the display of the value.

i see what you mean by saying that maybe i could do the math on the database side, but the calculation of this 3rd textbox (and of the other calculated textboxes i have on the form) are not that simple. i have oversimplified the example of calculation because i thought i wasnt relevant, but actually they have to do with calculating present values, exponentiated values, etc (financial calcs in general).

in that sense, what alternative method do you recommend to achieve what i want?

thanks
one thing that i should mention now that i have told you that calculations are financial, the simplified situation is this:
say 1st textbox is a future value. say 2nd textbox is an interest rate, and say 3rd textbox is the present value of textbox 1, and calculation takes into account both textboxes values (future value and interest rate).

Now, 1st texbox is bound the usual way and stores the value on database field. 2nd texbox is the interes rate, and assume for a second that this rate is pulled from the bank's database and is subject to change daily.

first time i create the form, user will input future value on tb1, interest rate will be pulled on tb2, and i will give the calculation on tb3. now suppose i want to store this on my database, all 3 values because i will do an automated report later and all textboxes' values have to appear. now say a week later somebody opens that form to make a change on the future value, when they open it, the future value will be the one stored a week before pulled from the database. the interest rate will be pulled from the mainframe, and could be different than the one a week ago. so, the calculation on tb3 can't be the one that was stored on the main database, because interest rates have changed and i wouldnt be reflecting that. so, tb3 has to be calculated always on the spot, and when user ends editing, the final value of tb3 has to go into database for reporting issues.

is it a bit clearer this way? thanks
ASKER CERTIFIED SOLUTION
Avatar of Sancler
Sancler

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
ok i have adapter your comments and suggestions to my code, and removed the _Format and _Parse event handlers since they, like you said, are mainly for display issues.

i have removed the binding for tb3, and wrote code in the _PositionChanged event of the BindingSource, using the BindingSource.Current("ColumnName") to assign the proper values to the datatable column so they could be persisted on call of the .EndEdit.

thank you very much for your help its been a life saver! (this approach i took here is basically the same one i took on my other related question, which you have also assisted me! here's the link just in case https://www.experts-exchange.com/questions/21902555/Manually-editing-content-of-datatable-row.html)

thanks again
P