databound inherited textbox can't keep changes to me.text

K

k

I created a custom textbox I named "NumericTextBox" by inheriting
from System.Windows.Forms.Textbox so I could filter keystroke input..

After changing the custom property "Precision", I desire to delete a certain
amount of digits from the "me.text". However, after changing the text
programatically, moving the focus to another control changes the text back
to the previous text.

Although calling EndCurrentEdit() on the BindingManagerBase prevents the
text from reverting, using EndCurrentEdit() in this fashion is not helpful.
This is because I am using the NumericTextBox on a form with "OK" and
"Cancel" buttons which use a currencymanager to apply or abandon changes via
CM.EndCurrentEdit or CM.CancelCurrentEdit.

The NumericTextBox needs to handle the digit deletion and application in a
generic way because it is used on multiple forms accross the project.
Here is a snippet of the NumericTextBox class:

Thanks,

k



'////////////////////////////////////////////
'// In the inherited textbox
'////////////////////////////////////////////
<Description("If IntegerOnly is FALSE, this property sets _
the allowed number of digits to the right of the decimal."), _
Browsable(True), _
Category("Validation"), _
DefaultValue(2)> _
Property Precision() As Integer
Get
Return m_Precision
End Get

Set(ByVal Value As Integer)
If Value >= 0 Then
m_Precision = Value

'// Look for a decimal
Dim i As Integer = Me.Text.IndexOf(".")

'// If we've a decimal AND Precision is larger than allowed
If i > -1 AndAlso (Me.Text.Length - (i + 1)) > Me.m_Precision Then

'// Trim off extra, disallowed digits
Me.Text = Me.Text.Remove(i + Me.m_Precision + 1, _
(Me.Text.Length - i - 1) - Me.m_Precision)

End If
End If
End Set
End Property



'////////////////////////////////////////////
'// And on the containing form
'////////////////////////////////////////////
Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnCancel.Click
cm.CancelCurrentEdit()
Me.m_parent.Focus()
Me.Close()
End Sub

Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnOK.Click
If ValidateForm() Then
cm.EndCurrentEdit()
Me.m_parent.Focus()
Me.Close()
End If
End Sub

Private Sub SetForm()
'// set a currency manager for this form to manage the appropriate
dataset tables
cm = CType(Me.BindingContext(Me.m_parent.DsMngMenu1.Taxes),
CurrencyManager)

'// If appropriate, Synchronize our Form to the record currently
selected in parent form
If m_actionToTake = formAction.editTax Then

'// set a currency manager for the owner form to find Form1's
current record position
cmOwner = CType(CType(Me.Owner, myns.mngMenu).BindingContext _
(Me.m_parent.DsMngMenu1.Taxes), CurrencyManager)

'// synchronize the table record positions between form1 and form2
Me.cm.Position = Me.cmOwner.Position
Else
'// create a new Tax
cm.AddNew()
End If

'// Set our databindings
Me.tbTaxName.DataBindings.Add("Text", Me.m_parent.DsMngMenu1.Taxes,
"TaxName")
Me.tbTaxSource.DataBindings.Add("Text", Me.m_parent.DsMngMenu1.Taxes,
"TaxSource")
Me.tbTaxValue.DataBindings.Add("Text", Me.m_parent.DsMngMenu1.Taxes,
"TaxValue")
Me.cbxTaxType.DataBindings.Add("SelectedItem",
Me.m_parent.DsMngMenu1.Taxes, "TaxType")

If Me.m_actionToTake = formAction.newTax Then
Me.cbxTaxType.SelectedIndex = 0
End Sub
 
K

Kathleen Dollard

This is just a hunch, but can you check that you're calling the base class
methods for any TextBox methods you're overriding. Particularly the
OnTextChanged method.
 
K

k

Thank you so much for responding, Kathleen. Here is the whole code for the
inherited Textbox. I tried both of the following, but neither seemed to
have an effect on the symptom.

MyBase.Text = Me.Text.Remove(i + Me.m_Precision + 1, (Me.Text.Length - i -
1) - Me.m_Precision)
and
Me.Text = Me.Text.Remove(i + Me.m_Precision + 1, (Me.Text.Length - i - 1) -
Me.m_Precision)

k



'// watch for text wrap from SMTP server
'//---------------------------------------

Imports System.ComponentModel

Public Class NumericTextbox
Inherits System.Windows.Forms.TextBox

Dim m_IntegerOnly As Boolean
Dim m_PositiveOnly As Boolean
Dim m_Precision As Integer
Dim m_PreviousPrecision As Integer = 2

<Description("If TRUE, only integers can be entered."), _
Browsable(True), _
Category("Validation"), _
DefaultValue(False), _
RefreshProperties(RefreshProperties.All)> _
Property IntegerOnly() As Boolean
Get
Return m_IntegerOnly
End Get
Set(ByVal Value As Boolean)
m_IntegerOnly = Value
If Value = True Then
Dim i As Integer = Me.Text.IndexOf(".")
If i <> -1 Then Me.Text.Remove(i, Me.Text.Length - i)
End If
End Set
End Property

<Description("If TRUE, only positive numbers can be entered."), _
Browsable(True), _
Category("Validation"), _
DefaultValue(False)> _
Property PositiveOnly() As Boolean
Get
Return m_PositiveOnly
End Get
Set(ByVal Value As Boolean)
Dim i As Integer = Me.Text.IndexOf("-")
If i <> -1 Then Me.Text.Remove(i, 1)

m_PositiveOnly = Value
End Set
End Property

<Description("If IntegerOnly is FALSE, this property sets the allowed
number of digits to the right of the decimal."), _
Browsable(True), _
Category("Validation"), _
DefaultValue(2)> _
Property Precision() As Integer
Get
Return m_Precision
End Get
Set(ByVal Value As Integer)
If Value >= 0 Then
m_Precision = Value

'// This block is commented out because without
bmb.EndCurrentEdit() the changed text
'// is lost from databinding, and with it, all changes in
parent form are accepted
'// without the ability to call
currencymanger.cancelCurrentEdit()

'//-------------------------------------------------------------------------
---------
''// if we have a decimal in the number AND the precision is
over the allowed amount.
'Dim i As Integer = Me.Text.IndexOf(".")
'If i > -1 AndAlso (Me.Text.Length - (i + 1)) >
Me.m_Precision Then
' '// trim off the disallowed precision digits from the
right.
' MyBase.Text = Me.Text.Remove(i + Me.m_Precision + 1,
(Me.Text.Length - i - 1) - Me.m_Precision)
'
Me.DataBindings.Item(0).BindingManagerBase.EndCurrentEdit()
'End If
End If
End Set
End Property


Private Sub NumericTextBox_KeyPress(ByVal sender As Object, ByVal e As
System.Windows.Forms.KeyPressEventArgs) Handles MyBase.KeyPress
Dim KeyAscii As Integer
KeyAscii = Asc(e.KeyChar) ' NOTE: used as a flag when = 0 to mark
bad values
Select Case KeyAscii
Case 48 To 57, 8, 13 ' Digits 0 - 9, Backspace, CR.
' These are OK, so accept them.

If Me.m_IntegerOnly = False Then
'// If we are in non-integer mode
If InStr(Me.Text, ".") <> 0 And Char.IsDigit(e.KeyChar)
Then '// & If we have a decimal already,
If (Me.Text.Length - Me.Text.IndexOf(".")) >
m_Precision Then '// check allowed precision.
KeyAscii = 0
'// if precision violation, discard keychar.
End If
End If
End If

Case 45 ' Minus sign.
If PositiveOnly Then
KeyAscii = 0
Else
' Number can have only one minus sign, so if
' we already have one, throw this one away.
If InStr(Me.Text, "-") <> 0 Then
KeyAscii = 0
End If
' If the insertion point is not sitting at zero
' (i.e., the beginning of the field), throw away
' the minus sign because it's not valid anywhere
' but the first position
If Me.SelectionStart <> 0 Then
KeyAscii = 0
End If
End If
Case 46 ' Period (decimal point).
If IntegerOnly Then
KeyAscii = 0
Else
' If we already have one period, throw it away
If InStr(Me.Text, ".") <> 0 Then
KeyAscii = 0
End If
End If
Case Else ' Provide no handling for other keys.
KeyAscii = 0
End Select

' If we want to throw the keystroke away, then set the event
' as already handled. Otherwise, let the keystroke be
' handled normally.
If KeyAscii = 0 Then
e.Handled = True
Else
e.Handled = False
End If
End Sub

End Class
 
K

k

alright. I was not able to find any other threads with an appropriate
answer to my question, I got no answer from anyone regarding this wierdness.
Soooooooo, I will post this workaround which i found works alright in my
situation in the hopes that this answer will help someone else who winds up
needing an answer to this question.

If you call "me.focus()" immediately prior to "me.tbValue='xxx'", the
databinding accepts the programatic change of the text box, and does the
push to the datasource.

If you fail to call "me.focus()" prior to the programatic change, the
programatic change just will not work. Apparently, databinding must use the
"leaving" event to fire off the data synchronization...

Of course, as I mentioned earlier in the thread, you can call
"Me.DataBindings.Item(0).BindingManagerBase.EndCurrentEdit()", to force the
change to be accepted, but this will remove your ability to call
"myCurrencyManager.CancelCurrentEdit()".


I think we would all be interested to read others' comments regarding this
and other suggested fixes or workarounds...


k
 

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