Xaisoft
Xaisoft

Reputation: 46651

TextChanged event only fires when I put my cursor in the textbox and change the text

I have a TextChanged Even on a textbox and when I enter data into it, it updates another textbox which in turn is supposed to fire a TextChanged Event, but it is not firing until I put my cursor in the TextBox. Is there a solution to this?

Code for updating the Extended Price when Qty Changes:

protected void txtQty1_TextChanged(object sender, EventArgs e)
    {
        if (txtQty1.Text != string.Empty && txtUnitPrice1.Text != string.Empty)
        {
            int qty = Convert.ToInt32(txtQty1.Text);
            double unitPrice = Convert.ToDouble(txtUnitPrice1.Text);

            double extendTotal1 = qty * unitPrice;

            txtExtPrice1.Text = extendTotal1.ToString();

        }
    }

Code for updating the extending price When Unit Price changes:

    protected void txtUnitPrice1_TextChanged(object sender, EventArgs e)
    {
        if (txtQty1.Text != string.Empty && txtUnitPrice1.Text != string.Empty)
        {
            int qty = Convert.ToInt32(txtQty1.Text);
            double unitPrice = Convert.ToDouble(txtUnitPrice1.Text);

            double extendTotal1 = qty * unitPrice;

            txtExtPrice1.Text = extendTotal1.ToString();

        }
    }

Finally, this should update the Grand Total When Extending Price Changes:

 protected void txtExtPrice1_TextChanged(object sender, EventArgs e)
    {

        if (txtExtPrice1.Text != string.Empty)
        {
            double extendedTotal1 = Convert.ToDouble(txtExtPrice1.Text);
            double grandTotal = Convert.ToDouble(txtGrandTotal.Text);

            grandTotal += extendedTotal1;

            txtGrandTotal.Text = grandTotal.ToString();
        }

    }

Is it true that I should probably make Grand Total a Static Variable?

Upvotes: 0

Views: 3540

Answers (5)

David Nelson
David Nelson

Reputation: 3714

Your basic problem here is that you are trying to use GUI controls to perform business logic. This is always a bad idea. GUI controls are designed to do one thing and one thing only: interact with the user. Trying to do anything else with them, such as perform calculations, will only lead to problems down the road.

Try reading up on the MVP (or MVVM) pattern. It will show you how you store the logical data for a view in a model, which is also where you do all your calculations. The GUI controls are merely updated when the corresponding data in the model changes. For example, a partial implementation of your model might look like this:

public class Model : INotifyPropertyChanged {

#region INotifyPropertyChanged implementation
   public event PropertyChangedEventHandler PropertyChanged;
   protected virtual void OnPropertyChanged(string propertyName) {
      var handler = PropertyChanged;
      if(null != handler)
         handler(this, new PropertyChangedEventArgs(propertyName));

      switch(propertyName){
         case Quantity:
         case UnitPrice:
            OnPropertyChanged("ExtendedPrice");
            break;
         case ExtendedPrice:
            OnPropertyChanged("Tax");
            OnPropertyChanged("GrandTotal");
            break;
         case Tax:
            OnPropertyChanged("GrandTotal");
            break;
      }
   }
#endregion

   private int _quantity;
   public int Quantity{
      get { return _quantity; }
      set {
         if (value != _quantity) {
            _quantity = value;
            OnPropertyChanged("Quantity");
         }
      }
   }

   private decimal _unitPrice;
   public decimal UnitPrice {
      get { return _unitPrice; }
      set {
         if (value != _unitPrice) {
            _unitPrice = value;
            OnPropertyChanged("UnitPrice");
         }
      }
   }

   public decimal ExtendedPrice {
      get { return Quantity * UnitPrice; }
   }

   public decimal Tax {
      get { return ExtendedPrice * TaxRate; }
   }

   public decimal GrandTotal {
      get { return ExtendedPrice + Tax; }
   }
}

Now, the controls in your view can be bound to the properties of your model, and you can be sure that no matter how the Quantity or UnitPrice is changed (whether by the user through the controls, or by your own code), the derived amounts will be changed accordingly.

Upvotes: 0

Steve Dignan
Steve Dignan

Reputation: 8560

Probably a silly question, but are all of these events hooked up to the corresponding controls?

If so, a breakpoint on the first row of each event should help you track down the problem super quick.

If not, there's your problem :).

UPDATE:
I believe I found your problem. If you are programatically setting a textbox value to the same value it already contains, the TextChanged event will NOT fire.

So, in your case, if you are changing the value in the txtQty1 or txtUnitPrice1 textboxes to the same value they already contain, then the value in the txtExtPrice1 textbox is programatically being updated to the same value it already contains; hence, your txtGrandTotal.Text property is not updating because the event that updates it (txtExtPrice1_TextChanged) is not being fired.

Upvotes: 0

Sujay Ghosh
Sujay Ghosh

Reputation: 2868

The textchanged event is not getting fired in the second textbox as it does not have the focus.

Add this line before , when you want to textchanged to fire.

txtBox2.Focus();

// do what you needto do witht the second text box.

txtBox1.Focus() ;

This should work

Sujay

Upvotes: 1

AllenG
AllenG

Reputation: 8190

No clue if this will help or not, since the code (mostly) worked for me, but I was getting odd totals in the Grand Total, so I changed the event handlers to "Validating" for Quantity and UnitPrice (and hooked them both to the same event handler, since they're doing exactly the same thing...) (EDIT:Yes, I faked some of the logic, including arbitrailly setting the GrandTotal if it was empty).

        private void textBox1_Validating(object sender, CancelEventArgs e)
    {
        if (!String.IsNullOrEmpty(textBox1.Text) && !String.IsNullOrEmpty(textBox2.Text))
        {
            int qty = int.Parse(textBox1.Text);
            double price = double.Parse(textBox2.Text);

            double totalPrice = qty * price;

            textBox3.Text = totalPrice.ToString();
        }
    }

    private void textBox3_TextChanged(object sender, EventArgs e)
    {
        double bTotal = double.Parse(textBox3.Text);
        if (String.IsNullOrEmpty(textBox4.Text)) textBox4.Text = "100.00";
        double gTotal = double.Parse(textBox4.Text);

        gTotal += bTotal;

        textBox4.Clear();
        textBox4.Text = gTotal.ToString();
    }

Upvotes: 1

TheTXI
TheTXI

Reputation: 37905

Just call the code to update the grand total from the first textchanged event and not worry about it not working when you try and cascade into another one.

Upvotes: 0

Related Questions