how to get both old and new value for a changed text box

K

Kathy

I would like to get the old and new value for a change made to a text
box so that I can store them in a change history table. What is the
best way to do this? I am just learning VB 2005; porting an
application from MS Access where I could just use the TextBox.OldValue
construct.

TIA,
Kathy
 
G

GhostInAK

Hello Kathy,

Usually nobody ever cares what the old value was. Most of the time the old
value is a non-value; It doesn't exist anymore, so we don't bother doing
anything with it.

If you really must absolutely have this horrid thing.. subclass a textbox
and add the functionality yourself.

-Boo
 
K

Kathy

GhostInAK said:
Hello Kathy,

Usually nobody ever cares what the old value was. Most of the time the old
value is a non-value; It doesn't exist anymore, so we don't bother doing
anything with it.

If you really must absolutely have this horrid thing.. subclass a textbox
and add the functionality yourself.

-Boo

In this application having the old value is critical for auditing
purposes. How would subclassing a textbox help get the old value?

Thanks.
Kathy
 
G

GhostInAK

Hello Kathy,

*ponders* How indeed. Could it be because then you could add your own property?
Something like.. oh I dunno.. .OldValue? Hmm.. I think mebe so.

-Boo
 
K

Kathy

GhostInAK said:
Hello Kathy,

*ponders* How indeed. Could it be because then you could add your own property?
Something like.. oh I dunno.. .OldValue? Hmm.. I think mebe so.

-Boo


Uh, that's real helpful.....I'm asking how and you have a sarcastic
answer like that.
Gee thanks.
 
M

Miro

Are these text boxes connected to a data record?

Perhaps make a "sister" table, and when the user comes into the record "on
change" you first make an exact copy of the record in that table.
On save, you compare the old record ( in sister ) and new record in normal
table and any fields that dont match, you have the old value.

Something we do in a different programming language ( and im too new to vb
to try it here, ) but we call it "scatter() "
and its a sub and what we do is before we go into the change of a record we
"scatter()". Scatter is a function that dumps
the whole data record to an array.

Every element in the array is equivalant to the corresponding field in the
datatable. So if in the datatable field 3 is "First Name",
then your scatter( 3 ) would be the value of the old first name.

My vb is too new however to give u the code for that. I guess you can
almost look at it as an ArrayList.

Miro
 
G

GhostInAK

Hello Kathy,

Help comes to those that help themselves. Why dont you press F1 and do a
little reading.

-Boo
 
G

GhostInAK

Hello Miro,

M-man.. no need for arrays. Array's are evil. Your scatter() functionality
is already baked into System.Data.DataRow.
Kathy however was not asking about database records, she was asking about
textboxes.

One a side note.. anytime you have to create a temp (or "sister", "sibling",
"inbred cousin", "might be related through marriage") table.. THINK REAL
HARD if that's the only way to accomplish your goals. Temp tables are a
good indicator of flawed design.

-Boo
 
J

JR

Kathy,

I'm relatively new to VB.NET but I would think that you could save the
text field when it gets focus and then compare it when it looses focus.
If it has changed you would have both fields. I understand what you
meant by the audit issue I have had similar issues in the past and
without sarcasm from people who don't understand business.

Jim
 
K

Kathy

JR said:
Kathy,

I'm relatively new to VB.NET but I would think that you could save the
text field when it gets focus and then compare it when it looses focus.
If it has changed you would have both fields. I understand what you
meant by the audit issue I have had similar issues in the past and
without sarcasm from people who don't understand business.

Jim

Thanks, Jim.
That sounds like a reasonable solution. Now I have to figure out how
to do it for 100+ fields without having to do on it on events specific
to each field. In MS Access you could use the AfterUpdate event for the
record and check for which field you are positioned in. What is the
equivalent in VB .Net? I've tried the TextChanged event for the form,
but it fires when the form is loaded and it does not seem to fire when
a change is made. I've also tried the DataMemberChanged for the
binding source, but it also doesn't fire when a field is changed. Any
ideas?
Kathy
 
K

Kathy

This is probably not the best way, but I discovered I can associate the
"Enter" focus event for all fields to that of a specific field to force
using the same code to capture the old value and get the field name
using the ActiveControl.Name. But when I use ActiveControl.Name in the
"Leave" focus event, it has the name of the NEXT control. The
ActiveControl.Name is also the next control name when used in the
Validated and Validating events as well. So what is the best way to
get the current field name after completing a change to that field (as
well as get the complete new value for that field)?

Thanks.
Kathy
 
B

Brian Tkatch

Kathy said:
I would like to get the old and new value for a change made to a text
box so that I can store them in a change history table. What is the
best way to do this? I am just learning VB 2005; porting an
application from MS Access where I could just use the TextBox.OldValue
construct.

TIA,
Kathy

There are two basic issues you are trying to address.

1) If it changed.
2) The old value.

Before looking into a VB answer to this, if this is being ported from
Access, you may now be using an actual database. In which case, you can
add a TRIGGER to be fired ON UPDATE, and capture the change at the
database level.

If the answer is to come from VB, a simple answer would be set the Tag
property to the old value as soon as the data is loaded. Then, when
storing the new data, compare it with the stored old value.

For mutiple textboxes, a loop could be employed. For example, to store
the data:

For Each Current_Control As Control In Me.Controls
If Current_Control.GetType Is GetType(TextBox) Then
Current_Control.Tag = Current_Control.Text
Next

HTH,
B.
 
S

Shane

Before the sarcastic fit from Boo (and please treat people the way that
you like to be treated, if you are annoyed, just don't respond), Boo's
idea of subclassing is a good idea, and it is what I do.

Here's the "how to".
This code was written under 2003, but works with 2005 as well.
By the way, I'm giving you a small subset of subclassing the text box.
Some tweaking may be needed.

The control will raise a "ValueChanged" event, if the text box "text"
changed on lost focus, instead of firing an event on every character
change, which is annoting!

1) Create a user control
2) Switch to Text editing mode
3) After you put in the "Inherits TextBox" line, you will no longer see
the user control on the design screen. The beauty of this method is
that any changes that Microsoft does to their Textbox control in the
future, your textbox will inherit the look and functionality as well.
4) When you're done, you replace all instances of the standard textbox
with your new textbox.

Replace text
Imports System.ComponentModel
Imports System.Text
Public Class YourControlName
Inherits TextBox
Private m_EnterValue As String = ""
Public Event ValueChanged(ByVal sender As Object, ByVal e As
System.EventArgs)

Overloads Property Text(ByVal FormatData As Boolean) As String
Get
Text = Me.Text
End Get
Set(ByVal Value As String)
Me.Text = Value
m_EnterValue = Me.Text
End Set
End Property

Property EnterValue() As String
Get
EnterValue= m_EnterValue
End Get
Set(ByVal Value As String)
m_EnterValue = Value
End Set
End Property

Private Sub YourControlName_Leave(ByVal sender As Object, ByVal e
As System.EventArgs) Handles MyBase.Leave
If m_EnterValue <> Me.Text Then RaiseEvent ValueChanged(sender,
e)
End Sub
End Class
 
B

BK

Here are some thoughts that might help. Our approach is to have middle
tier classes that handle all data I/O. Each of these classes has
public members that represent the fields in the back end database.
They also have a uniform set of methods (an interface) to access the
typical functionality.

As a small example, lets say we have an employee table that only has 3
fields, LastName, FirstName, and EmployeeId. Lets say we write a class
named EmployeeClass, it would have 3 public members:

Public LastName As String
Public FirstName As String
Public EmployeeId As String

The class would also have Load, Add, Update, and Delete methods. If I
had some form to allow editing a record, here's how the code would look
to populate the textboxes with values from the table:

Outside any methods in the form (so as to make it public to the form)
Dim EmployeeObject as New EmployeeClass()

Inside some method such as OnLoad:

EmployeeObject.Load(EmployeeId)
Me.TextBoxLastName.Text = EmployeeObject.LastName
Me.TextBoxFirstName.Text = EmployeeObject.FirstName
Me.TextBoxEmployeeId.Text = EmployeeObject.EmployeeId


To keep an audit trail, I might do something like this (assuming we are
in some kind of Save method):

If Me.TextBoxLastName.Text <> EmployeeObject.LastName
'Write the old and/or new value to an audit table or whatever you
want
Endif

The same code would apply to the other two textboxes. Since the class
retrieved the data, it isn't directly bound to the textbox, therefore I
can compare the retrieved value to the value in the textbox. The heavy
lifting is done by the EmployeeObject, it takes a bit more work to
create, but the payoff is in flexibility.

I hope this helps, but if you some clarification, let me know and I'll
help as much as I can.
 
K

Kathy

Brian,

I have set this up to work with either a MS Access or SQL Server
database. I think I've accomplished both issues now. Inside the LEAVE
event I'm comparing the old to the new value as suggested by Jim.
Inside the ENTER event I was storing the value in a global variable.
But I like your idea of using the Tag property for saving the old value
better than what I did. That way I can compare all the text boxes
during the binding source's CurrentChanged event. Does that sound
reasonable?

Thanks !
Kathy
 
K

Kathy

Thanks all, for your contributions.
I have it working now by setting the old value in the Tag property
recommended by Brian. Then prior to going to a new record, I loop
through the fields checking for old values not matching new values and
then insert the appropriate audit records as appropriate.
Kathy
 
G

GhostInAK

Hello Shane,

Hell with you Shane. I volunteer my time here. I aint gettin paid for this
crap. You dont like my attitude, fuk off.

-Boo
 
M

mg

GhostInAK said:
Hell with you Shane. I volunteer my time here. I aint gettin paid for this
crap. You dont like my attitude, fuk off.

Well Ghost, with sarcastic, unhelpful answers like above why bother
wasting your valuable time? It seems you have enough free time to
waste someone else's time with your non-answer. No offence, but how
old are you?
 
G

GhostInAK

Hello mg,

NON-ANSWER!? Fukin retard. It was a perfect answer. It was EXACTLY what
the OP should have done. But no.. she used the freakin Tag property instead..
why? Because she's afraid of a lil work.

I'll remind you of the answer: If you really must absolutely have this horrid
thing.. subclass a textbox and add the functionality yourself.

Followed by: *ponders* How indeed. Could it be because then you could add
your own property?
Something like.. oh I dunno.. .OldValue? Hmm.. I think mebe so.

Did she take the advice? No.. All she saw was the sarcasm.. and it wasnt
really even sarcasm. She cut her own throat out of spite. I have no pity
for any of you.

-Boo
 
I

Izzy

Something else you might think about Kathy,

I usually read data directly into controls like textbox's using a data
reader. I did work on a project in my early days of .NET where we used
a Currency Manager and the controls were bound too the DataTable. In
this set up, before the Table.AcceptChanges() method is called the
table actually contains the original value and proposed value.

This way there would be no reason to check every control individually.

Do some reading in the BOL about DataTables and Currency Managers.

Additionally, you mentioned Sql Server, if this is the database your
using then I would put an Update Trigger on the table and when it
fires, insert the old record into an identical table.

On another note.....

Sorry about the sarcastic feedback you got, in our line of work their
seems to be a lot if idiots with god syndrome.

Izzy
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top