Best way to limit textbox decimal input in c# - c#

How can I make a textbox in which can be only typed a number like 12.00 or 1231231.00 or 123123
I've done this in a very long way and I'm looking for the best and fastest way.
Also the decimal separator must be culture specific.:
Application.CurrentCulture.NumberFormat.NumberDecimalSeparator

The Validating event was made to do that. Drop an ErrorProvider control on your form so you can subtly remind the user that she did something wrong. The event also allows you to format the text box text the way that make sense. Like this:
private void textBox1_Validating(object sender, CancelEventArgs e) {
// Empty strings okay? Up to you.
if (textBox1.Text.Length > 0) {
decimal value;
if (decimal.TryParse(textBox1.Text, out value)) {
textBox1.Text = value.ToString("N2");
errorProvider1.SetError(textBox1, "");
}
else {
e.Cancel = true;
textBox1.SelectAll();
errorProvider1.SetError(textBox1, "Please enter a number");
}
}
}

That's a fairly straightforward operation. You'll need to filter the keys that you don't want out and then perform some additional checks.
Add the following code to the KeyDown event of the textbox:
private void TextBox1_KeyDown(object sender,
System.Windows.Forms.KeyEventArgs e)
{
switch (e.KeyCode) {
case Keys.D0:
case Keys.D1:
case Keys.D2:
case Keys.D3:
case Keys.D4:
case Keys.D5:
case Keys.D6:
case Keys.D7:
case Keys.D8:
case Keys.D9:
case Keys.NumPad0:
case Keys.NumPad1:
case Keys.NumPad2:
case Keys.NumPad3:
case Keys.NumPad4:
case Keys.NumPad5:
case Keys.NumPad6:
case Keys.NumPad7:
case Keys.NumPad8:
case Keys.NumPad9:
//allow numbers only when no modifiers are active
if (e.Control || e.Alt || e.Shift) {
//suppress numbers with modifiers
e.SuppressKeyPress = true;
e.Handled = true;
Interaction.Beep();
}
break;
case (Keys)110:
case Keys.OemPeriod:
if (!((TextBox)sender).Text.Contains(".")) {
//allow period key if there is no '.'
//in the text and no modifiers are active
if (e.Control || e.Alt || e.Shift) {
//suppress numbers with modifiers
e.SuppressKeyPress = true;
e.Handled = true;
Interaction.Beep();
}
} else {
e.SuppressKeyPress = true;
e.Handled = true;
Interaction.Beep();
}
break;
case Keys.Subtract:
case Keys.OemMinus:
if (((TextBox)sender).SelectionStart == 0 &&
!((TextBox)sender).Text.Contains("-")) {
//allow the negative key only when the cursor
//is at the start of the textbox
//and there are no minuses in the textbox
//and no modifiers are active
if (e.Control || e.Alt || e.Shift) {
//suppress numbers with modifiers
e.SuppressKeyPress = true;
e.Handled = true;
Interaction.Beep();
}
} else {
e.SuppressKeyPress = true;
e.Handled = true;
Interaction.Beep();
}
break;
case Keys.C:
case Keys.X:
case Keys.V:
case Keys.Z:
//allow copy, cut, paste & undo by checking for
//the CTRL state.
if (e.Control == false) {
e.SuppressKeyPress = true;
e.Handled = true;
Interaction.Beep();
}
break;
case Keys.Control:
case Keys.ControlKey:
case Keys.Alt:
case Keys.Shift:
case Keys.ShiftKey:
//allow control, alt & shift
break;
case Keys.Left:
case Keys.Right:
case Keys.Up:
case Keys.Down:
case Keys.PageUp:
case Keys.PageDown:
case Keys.Home:
case Keys.End:
//allow navigation keys
break;
case Keys.Back:
case Keys.Delete:
//allow backspace & delete
break;
default:
//suppress any other key
e.SuppressKeyPress = true;
e.Handled = true;
Interaction.Beep();
break;
}
}
And then, since a user may paste values into the textbox, you add the following to the TextBox's Validate event
private void TextBox1_Validating(object sender,
System.ComponentModel.CancelEventArgs e)
{
//just in case a value was pasted,
//we'll need to validate the value
if (!Information.IsNumeric(((TextBox)sender).Text))
{
e.Cancel = true;
}
}
I wrote a class to handle a variety of filters for you [which obviously includes the culture-specific decimal symbol].
Add this class to your project
using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
public class TextBoxFilter
{
[Flags()]
public enum Filters
{
None = 0,
Text = 1,
Numbers = 2,
AlphaNumeric = Filters.Text | Filters.Numbers,
Currency = 4,
All = Filters.Text | Filters.Numbers | Filters.Currency
}
Dictionary<TextBox, Filters> _keyFilter;
Dictionary<TextBox, string> _allowedKeys;
Dictionary<TextBox, string> _invalidKeys;
Dictionary<TextBox, Windows.Forms.KeyEventArgs> keyEventArgs;
private static string DecimalMark = Application.CurrentCulture.NumberFormat.NumberDecimalSeparator;
private static string NegativeMark = Application.CurrentCulture.NumberFormat.NegativeSign;
private static string CurrencySymb = Application.CurrentCulture.NumberFormat.CurrencySymbol;
private static string CurrencyDecimal = Application.CurrentCulture.NumberFormat.CurrencyDecimalSeparator;
public TextBoxFilter()
{
_keyFilter = new Dictionary<TextBox, Filters>();
_allowedKeys = new Dictionary<TextBox, string>();
_invalidKeys = new Dictionary<TextBox, string>();
keyEventArgs = new Dictionary<TextBox, KeyEventArgs>();
}
//set & remove filter
public void SetTextBoxFilter(TextBox textBox, Filters filter)
{
SetTextBoxFilter(textBox, filter, AllowedKeys(textBox), InvalidKeys(textBox));
}
public void SetTextBoxFilter(TextBox textBox, string allowedKeys)
{
SetTextBoxFilter(textBox, Strings.Filter(textBox), allowedKeys, InvalidKeys(textBox));
}
public void SetTextBoxFilter(TextBox textBox, string allowedKeys, string invalidKeys)
{
SetTextBoxFilter(textBox, Strings.Filter(textBox), allowedKeys, invalidKeys);
}
public void SetTextBoxFilter(TextBox textBox, Filters filter, string allowedKeys, string invalidKeys)
{
if (!_keyFilter.ContainsKey(textBox)) {
//add the textbox and its filter if it does not exist in
//the collection of registered textboxes
_keyFilter.Add(textBox, filter);
_allowedKeys.Add(textBox, allowedKeys);
_invalidKeys.Add(textBox, invalidKeys);
keyEventArgs.Add(textBox, new System.Windows.Forms.KeyEventArgs(Keys.None));
//add the event handlers
textBox.KeyDown += KeyDownUp;
textBox.KeyUp += KeyDownUp;
textBox.KeyPress += KeyPress;
textBox.Validating += Validating;
textBox.Disposed += Disposed;
} else {
//change the filter of the textbox if it exists in
//the collection of registered textboxes
_keyFilter(textBox) = filter;
_allowedKeys(textBox) = allowedKeys;
_invalidKeys(textBox) = invalidKeys;
}
}
public void RemoveTextBoxFilter(TextBox textBox)
{
if (_keyFilter.ContainsKey(textBox)) {
_keyFilter.Remove(textBox);
_allowedKeys.Remove(textBox);
_invalidKeys.Remove(textBox);
keyEventArgs.Remove(textBox);
textBox.KeyDown -= KeyDownUp;
textBox.KeyUp -= KeyDownUp;
textBox.KeyPress -= KeyPress;
textBox.Validating -= Validating;
textBox.Disposed -= Disposed;
}
}
public bool ContainsTextBox(TextBox textBox)
{
return _keyFilter.ContainsKey(textBox);
}
//properties
public Filters Filter {
get {
if (ContainsTextBox(textBox)) {
return _keyFilter.Item[textBox];
} else {
return Filters.None;
}
}
set { SetTextBoxFilter(textBox, value); }
}
public string AllowedKeys {
get {
if (ContainsTextBox(textBox)) {
return _allowedKeys(textBox);
} else {
return "";
}
}
set { SetTextBoxFilter(textBox, this.Filter(textBox), value, this.InvalidKeys(textBox)); }
}
public string InvalidKeys {
get {
if (ContainsTextBox(textBox)) {
return _invalidKeys(textBox);
} else {
return "";
}
}
set { SetTextBoxFilter(textBox, this.Filter(textBox), this.AllowedKeys(textBox), value); }
}
//event handlers
private void Disposed(object sender, System.EventArgs e)
{
RemoveTextBoxFilter((TextBox)sender);
}
private void KeyDownUp(object sender, System.Windows.Forms.KeyEventArgs e)
{
//assign the modifiers
keyEventArgs((TextBox)sender) = e;
}
private void KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
//ensure key pressed is in the allowed keys
object txt = (TextBox)sender;
object c = e.KeyChar;
bool allowKey = IsValidChar(txt, c, txt.SelectionStart);
//check for backspace & Ctrl combinations if the allowKey is still false
if (allowKey == false) {
if (keyEventArgs(txt).Control) {
//control modifier goes with A, X, C, V and Z for
//Select All, Cut, Copy, Paste and Undo respectively
object key = keyEventArgs(txt).KeyCode;
allowKey = (key == Keys.A || key == Keys.X || key == Keys.C || key == Keys.V || key == Keys.Z);
} else if (keyEventArgs(txt).KeyCode == Keys.Back) {
//allow the backspace key
allowKey = true;
}
}
//disable the key if it was not valid
if (!allowKey) {
e.Handled = true;
Interaction.Beep();
}
}
private void Validating(object sender, System.ComponentModel.CancelEventArgs e)
{
object box = (TextBox)sender;
object boxFlags = _keyFilter(box);
//skip validation if the textbox allows all entries or there is no text
if (boxFlags == Filters.All | string.IsNullOrEmpty(box.Text))
return;
//otherwise check the characters entered
object txtChars = box.Text.ToCharArray;
bool isValidEntry = false;
//check each caracter for an invalid entry
for (i = 0; i <= txtChars.Length - 1; i++) {
object c = txtChars(i);
isValidEntry = IsValidChar(box, txtChars(i), i);
if (!isValidEntry) {
box.Select(i, 1);
break; // TODO: might not be correct. Was : Exit For
}
}
if (!isValidEntry)
e.Cancel = true;
if (!isValidEntry) {
Interaction.MsgBox("The text entered is invalid for the format " + boxFlags.ToString + "." + !string.IsNullOrEmpty(_allowedKeys(box)) ? Constants.vbCrLf + "Additional Allowed Keys: " + _allowedKeys(box) : "" + !string.IsNullOrEmpty(_invalidKeys(box)) ? Constants.vbCrLf + "Additional Invalid Keys: " + _invalidKeys(box) : "", MsgBoxStyle.Critical, "Invalid Entry");
}
}
private bool IsValidChar(TextBox textBox, char c, int charIndex)
{
//ensure key pressed is in the allowed keys
object pF = _keyFilter(textBox);
object aK = _allowedKeys(textBox);
object iK = _invalidKeys(textBox);
bool shouldAllow = false;
//if filter is set to all, return true unconditionally
if (pF == Filters.All)
return true;
//check preset filters
//check for text
if (EnumHasFlag(pF, Filters.Text)) {
if (!char.IsDigit(c)) {
shouldAllow = true;
} else {
//if the character is a digit, check for the number flag (AlphaNumerics)
if (EnumHasFlag(pF, Filters.Numbers)) {
shouldAllow = true;
}
}
}
//check for nubers
if (shouldAllow == false && EnumHasFlag(pF, Filters.Numbers)) {
if (char.IsDigit(c)) {
shouldAllow = true;
} else if (DecimalMark.Contains(c)) {
//allow the decimal if there is no decimal in the textbox's
//text or the selected text contains the mark
if (!textBox.Text.Substring(0, charIndex).Contains(c) || textBox.SelectedText.Contains(c)) {
shouldAllow = true;
}
} else if (NegativeMark.Contains(c) && (charIndex <= NegativeMark.IndexOf(c))) {
//allow the negative mark if we are at the start of the
//textbox
shouldAllow = true;
}
}
//check for currency
if (shouldAllow == false && EnumHasFlag(pF, Filters.Currency)) {
if (char.IsDigit(c)) {
shouldAllow = true;
} else if (CurrencyDecimal.Contains(c)) {
//allow the currency decimal mark if it does not exist in the
//textbox's text or the selected text contains the mark
if (!textBox.Text.Substring(0, charIndex).Contains(c) || textBox.SelectedText.Contains(c)) {
shouldAllow = true;
}
} else if (CurrencySymb.Contains(c) && (charIndex <= CurrencySymb.IndexOf(c))) {
//allow the currency symbol if we are in a valid position
shouldAllow = true;
}
}
//now check for extra allowed keys
if (!shouldAllow) {
shouldAllow = aK.Contains(c);
}
//and then check for extra invalid keys
if (shouldAllow && iK.Contains(c)) {
shouldAllow = false;
}
return shouldAllow;
}
[System.Diagnostics.DebuggerStepThrough()]
private bool EnumHasFlag(Enum value, Enum flag)
{
return (Convert.ToInt64(value) & Convert.ToInt64(flag)) == Convert.ToInt64(flag);
}
}
and then use it in your form as follows
public class Form1
{
TextBoxFilter filter = new TextBoxFilter();
private void Form1_Load(object sender, System.EventArgs e)
{
filter.SetTextBoxFilter(TextBox1, TextBoxFilter.Filters.Numbers);
}
public Form1()
{
Load += Form1_Load;
}
}

Try the MaskedTextBox control.

private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (!Char.IsNumber(e.KeyChar))
{
e.Handled = !(((TextBox)sender).SelectionStart != 0 && (e.KeyChar.ToString() == Application.CurrentCulture.NumberFormat.NumberDecimalSeparator && ((TextBox)sender).Text.IndexOf(Application.CurrentCulture.NumberFormat.NumberDecimalSeparator) == -1));
}
}
And you should check onLeave for Length == 0 I think...

Related

how to bind keyboard numbers with a calculator app that i created?

Hi I have created a window calculator and it is working fine however, i want to be able to use my keyboard numbers as well for my calculator app . what do i do? here is my code
public partial class Form1 : Form
{
Double resultValue = 0;
String operationPerformed = "";
bool isOperationPerformed = false;
public Form1()
{
InitializeComponent();
}
private void button_click(object sender, EventArgs e)
{
if ((textBox_Result.Text == "0") || (isOperationPerformed))
textBox_Result.Clear();
isOperationPerformed = false;
Button button = (Button)sender;
if (button.Text == ".")
{
if (!textBox_Result.Text.Contains("."))
textBox_Result.Text = textBox_Result.Text + button.Text;
} else
textBox_Result.Text = textBox_Result.Text + button.Text;
}
private void operator_click(object sender, EventArgs e)
{
Button button = (Button)sender;
if (resultValue != 0)
{
EqualsToBtn.PerformClick();
operationPerformed = button.Text;
labelCurrentOperation.Text = resultValue + " " + operationPerformed;
isOperationPerformed = true;
}else
{
operationPerformed = button.Text;
resultValue = Double.Parse(textBox_Result.Text);
labelCurrentOperation.Text = resultValue + " " + operationPerformed;
isOperationPerformed = true;
}
}
private void RefreshBtn_Click(object sender, EventArgs e)
{
textBox_Result.Text = "0";
}
private void CancelBtn_Click_1(object sender, EventArgs e)
{
textBox_Result.Text = "0";
resultValue = 0;
}
private void EqualsToBtn_Click_1(object sender, EventArgs e)
{
switch (operationPerformed)
{
case "+":
textBox_Result.Text = (resultValue + Double.Parse(textBox_Result.Text)).ToString();
break;
case "-":
textBox_Result.Text = (resultValue - Double.Parse(textBox_Result.Text)).ToString();
break;
case "*":
textBox_Result.Text = (resultValue * Double.Parse(textBox_Result.Text)).ToString();
break;
case "/":
textBox_Result.Text = (resultValue / Double.Parse(textBox_Result.Text)).ToString();
break;
}
resultValue = Double.Parse(textBox_Result.Text);
labelCurrentOperation.Text = "";
}
}
}
You can achieve it by subscribing to KeyDown event.
Fisrt, need to set KeyPreview to true.
public Form1()
{
InitializeComponent();
KeyPreview = true;
}
Then use swicth to judge which key pressed. Keys Enum
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.NumPad0:
case Keys.D0:
// Zero
buttonnum0.PerformClick(); // simulate pressing buttonnum0
break;
case Keys.NumPad1:
case Keys.D1:
// One
buttonnum1.PerformClick();
break;
// ... etc
case Keys.Oemplus:
case Keys.Add:
// Plus
buttonplus.PerformClick();
break;
default:
return;
}
e.Handled = true;
}
You can use the processcmdkey
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
if (keyData == ( Keys.Numpad0 | Keys.Numpad0)) { // just an example, handle the rest as you need
doSomething();
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}

TextBox handled doesn't work in some case

I have textbox and when i create that form i pass some values and then i prevent user to input some things into textbox based on passed values with this code:
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (!brojevi && char.IsDigit(e.KeyChar))
{
e.Handled = true;
return;
}
if (!slova && char.IsLetter(e.KeyChar))
{
e.Handled = true;
return;
}
if (!znakovi && char.IsPunctuation(e.KeyChar) || !znakovi && char.IsSymbol(e.KeyChar))
{
e.Handled = true;
return;
}
if (!razmak && char.IsSeparator(e.KeyChar))
{
e.Handled = true;
return;
}
if (maxKaraktera != -1 && (textBox1.Text.Length + 1) > maxKaraktera)
{
e.Handled = true;
return;
}
if (String.IsNullOrWhiteSpace(textBox1.Text))
{
return;
}
if (maxBroj != -1 && Convert.ToDouble(textBox1.Text) > maxBroj)
{
e.Handled = true;
return;
}
}
Problem is that i enabled brojevi and set maxBroj to 10
Now when i try typing some char, it checks and see that slova is not true, set e.Handled = true and return and in my textbox that char is not imputed which is ok.
But when i try inserting number which is greater than 10 (let's say 12), it goes to if statement where it checks if(maxBroj != -1 && Convert.ToDoube(textBox1.Text) > maxBroj) and it enters it, set e.Handled = true and return but number is implemented in textbox.
Why this happens?
EDIT: Code from creating form and form that has textbox
Creating from:
MessageBoxWithValue msg = new MessageBoxWithValue("Unesite kolicinu", "Unesite zeljenu kolicinu. Maksimum: " + aa.maxKolicina.ToString());
msg.brojevi = true;
msg.maxBroj = aa.maxKolicina;
msg.ShowDialog();
if(msg.DialogResult == DialogResult.OK)
{
kol = Convert.ToDouble(msg.returnValue);
}
else
{
return;
}
Here is MessageBoxWithValue form:
public partial class MessageBoxWithValue : Form
{
public bool brojevi = false;
public bool slova = false;
public bool znakovi = false;
public bool razmak = false;
public double maxBroj = -1;
public int maxKaraktera = -1;
public string returnValue;
public MessageBoxWithValue(string naslov, string opis)
{
InitializeComponent();
this.Text = naslov;
label1.Text = opis;
}
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (!brojevi && char.IsDigit(e.KeyChar))
{
e.Handled = true;
return;
}
if (!slova && char.IsLetter(e.KeyChar))
{
e.Handled = true;
return;
}
if (!znakovi && char.IsPunctuation(e.KeyChar) || !znakovi && char.IsSymbol(e.KeyChar))
{
e.Handled = true;
return;
}
if (!razmak && char.IsSeparator(e.KeyChar))
{
e.Handled = true;
return;
}
if (maxKaraktera != -1 && (textBox1.Text.Length + 1) > maxKaraktera)
{
e.Handled = true;
return;
}
if (String.IsNullOrWhiteSpace(textBox1.Text))
{
return;
}
if (maxBroj != -1 && Convert.ToDouble(textBox1.Text) > maxBroj)
{
e.Handled = true;
return;
}
}
private void button2_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.Cancel;
this.Close();
}
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.Enter || e.KeyCode == Keys.Return)
{
Uspesno();
}
}
private void button1_Click(object sender, EventArgs e)
{
Uspesno();
}
private void Uspesno()
{
this.DialogResult = DialogResult.OK;
returnValue = textBox1.Text;
}
}
But when i try inserting number which is greater than 10 (let's say 12), it goes to if statement where it checks if(maxBroj != -1 && Convert.ToDoube(textBox1.Text) > maxBroj) and it enters it, set e.Handled = true and return but number is implemented in textbox.
I hope I've got your issue right. You are trying to filter numbers by their values (e.g. maxBroj is set to 10) and you are expecting
if (maxBroj != -1 && Convert.ToDouble(textBox1.Text) > maxBroj)
{
e.Handled = true;
return;
}
not to allow entering a number >10. Unfortunately this will not work as intended, since textBox1.Text won't be set until the KeyPress event handler has finished.
Let's say you are entering 14. When the first KeyPress event is raised (1), textBox1.Text is empty. You are returning from
if (String.IsNullOrWhiteSpace(textBox1.Text))
{
return;
}
Afterwards textBox1.Text is set to "1". Then the second KeyPress event is raised. textBox1.Text is "1", hence the method won't enter the block
if (maxBroj != -1 && Convert.ToDouble(textBox1.Text) > maxBroj)
{
e.Handled = true;
return;
}
Afterwards textBox1.Text will be set to "14", but this is too late for your validation.
You'll have to calculate the expected new value. Please see this question on how to insert the new character in the existing string.

Need help figuring out repeatable equals and addition operator events

I am building a UWP calculator app using the MVVM pattern and I have just about everything figured out except how to get the equals button to calculate repeatedly and have my operator buttons work correctly. I can do one or the other, but I can't figure out how to do both. The code below works for a repeatable equals button, but the plus operator will yield the wrong answer when adding multiple values.
If I take out the second switch statement and change the variables back to using one Output variable then I can get the plus operator to work, but the equals button will fail when it repeats.
I am sure it is just a matter of adding a nested if statement or the addition of a bool somewhere, but I'm stumped! Please help. I've removed the non essential buttons and operators. Any other helpful suggestions on my code would be appreciated too.
Thank you!
public class ComputareViewModel : ViewModelBase
{
#region Private Fields
private double resultNumber = 0;
private double xResultNumber;
private double yResultNumber;
private string _outputValue = "0";
bool isOperationPerformed = false;
bool EqualsRepeated = false;
public ComputareViewModel()
{
}
public string OutputValue
{
get
{
return _outputValue;
}
set
{
_outputValue = value;
OnPropertyChanged("OutputValue");
}
}
public void OnNumberBtnClick(object sender, RoutedEventArgs args)
{
if ((_outputValue) == "0" || (isOperationPerformed))
_outputValue = "";
isOperationPerformed = false;
Button numberBtnClick = (Button)sender;
if ((string)numberBtnClick.Content == ".")
{
if (!_outputValue.Contains("."))
{
OutputValue = OutputValue + numberBtnClick.Content;
}
}
else
{
OutputValue = OutputValue + numberBtnClick.Content;
}
}
public void OnOperatorBtnClick(object sender, RoutedEventArgs args)
{
Button operatorBtnClick = (Button)sender;
if(isOperationPerformed == false)
{
if (xResultNumber != 0)
{
OnEqualsBtnClick(this, new RoutedEventArgs());
operationPerformed = (string)operatorBtnClick.Content;
isOperationPerformed = true;
EqualsRepeated = false;
}
else
{
operationPerformed = (string)operatorBtnClick.Content;
xResultNumber = Double.Parse(OutputValue);
isOperationPerformed = true;
}
}
else
{
//Do nothing.
}
}
public void OnEqualsBtnClick(object sender, RoutedEventArgs args)
{
if (EqualsRepeated == false)
{
if (double.TryParse(OutputValue, out yResultNumber))
switch (operationPerformed)
{
case "+":
{
OutputValue = (xResultNumber + yResultNumber).ToString();
break;
}
}
isOperationPerformed = true;
EqualsRepeated = true;
}
else
{
// If equals has already been clicked
if (EqualsRepeated == true)
if (double.TryParse(OutputValue, out xResultNumber))
switch (operationPerformed)
{
case "+":
{
OutputValue = (xResultNumber + yResultNumber).ToString();
break;
}
}
}
isOperationPerformed = true;
}
}
There are some logical problems in your code. First, after OnEqualsBtnClick is called, isOperationPerformed is true, if you want to call the OnOperatorBtnClick, it will always go to the else part and do nothing. Second, if you repeat click euqal button, xResultNumber is not 0, if you want to call OnOperatorBtnClick, it will then call the OnEqualsBtnClick, but EqualsRepeated is true now, so you should change EqualsRepeated to false. At last, xResultNumber is the value of last calculation, you should set it to 0 in OnEqualsBtnClick method.
So you can change your code like this:
public void OnOperatorBtnClick(object sender, RoutedEventArgs args)
{
Button operatorBtnClick = (Button)sender;
EqualsRepeated = false;
if (isOperationPerformed == false)
{
if (xResultNumber != 0)
{
OnEqualsBtnClick(this, new RoutedEventArgs());
operationPerformed = (string)operatorBtnClick.Content;
isOperationPerformed = true;
EqualsRepeated = false;
}
else
{
operationPerformed = (string)operatorBtnClick.Content;
xResultNumber = Double.Parse(OutputValue);
isOperationPerformed = true;
}
}
else
{
//Do nothing.
}
}
public void OnEqualsBtnClick(object sender, RoutedEventArgs args)
{
if (EqualsRepeated == false)
{
if (double.TryParse(OutputValue, out yResultNumber))
switch (operationPerformed)
{
case "+":
{
OutputValue = (xResultNumber + yResultNumber).ToString();
break;
}
}
isOperationPerformed = true;
EqualsRepeated = true;
}
else
{
// If equals has already been clicked
if (EqualsRepeated == true)
if (double.TryParse(OutputValue, out xResultNumber))
switch (operationPerformed)
{
case "+":
{
OutputValue = (xResultNumber + yResultNumber).ToString();
break;
}
}
}
isOperationPerformed = false;
xResultNumber = 0;
}

Two simultaneous Textchanged Events firing in Winforms C#

When I type in the first textbox, it should run a conversion which appears in the second, and when I type in the second, it will appear in the first. However, when I type in the first textchanged event, it triggers the second, which disrupts entering in the first and vice versa. Is there a way I can disable firing the textchanged event when it is highlighted or something?
public void dB10_TextChanged(object sender, EventArgs e)
{
TextBox dB10 = sender as TextBox;
double dBV;
int i = dB10.Text.Trim().Length;
if (i > 0)
{
dBV = Convert.ToDouble(dB10.Text);
}
else
return;
UnitConverter dBConverter = new UnitConverter();
// Controls for if various radiobuttons were clicked
if (dBVRadio.Checked == true)
{
dBV = dBConverter.dBVToVolts(dBV);
voltage.Text = dBV.ToString();
}
else if (dBuRadio.Checked == true)
{
dBV = dBConverter.dBuToVolts(dBV);
voltage.Text = dBV.ToString();
}
}
public void voltage_TextChanged(object sender, EventArgs e)
{
TextBox voltage = sender as TextBox; //V >> dB10 (dBV/dBu)
int i = voltage.Text.Trim().Length;
double volts;
if (i > 0)
{
volts = Convert.ToDouble(voltage.Text);
}
else
return;
UnitConverter dBConverter = new UnitConverter();
if (dBVRadio.Checked == true)
{
dBuRadio.Checked = false;
volts = dBConverter.voltsTodBV(volts);
dB10.Text = volts.ToString();
}
else if (dBuRadio.Checked == true)
{
volts = dBConverter.voltsTodBu(volts);
dB10.Text = volts.ToString();
}
}
you can remove the handler of another textbox and then add it
public void dB10_TextChanged(object sender, EventArgs e)
{
voltage.TextChanged-= voltage_TextChanged;
TextBox dB10 = sender as TextBox;
double dBV;
int i = dB10.Text.Trim().Length;
if (i > 0)
{
dBV = Convert.ToDouble(dB10.Text);
}
else
return;
UnitConverter dBConverter = new UnitConverter();
// Controls for if various radiobuttons were clicked
if (dBVRadio.Checked == true)
{
dBV = dBConverter.dBVToVolts(dBV);
}
else if (dBuRadio.Checked == true)
{
dBV = dBConverter.dBuToVolts(dBV);
}
voltage.Text = dBV.ToString();
voltage.TextChanged+= voltage_TextChanged;
}
You can just use a bool variable:
bool escape = false;
public void dB10_TextChanged(object sender, EventArgs e)
{
if(escape)
return;
escape = true;
// your code
escape = false;
}
public void voltage_TextChanged(object sender, EventArgs e)
{
if(escape)
return;
escape = true;
// your code
escape = false;
}

Capturing ctrl + multiple key downs

Is there an easy way to capture a ctrl+key1, key2 event in a winforms app similar to that in visual studio such as ctrl+e, c = comment out selected lines?
I am currently overriding my forms OnKeyDown event:
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
if (e.Control && e.KeyCode.ToString() == "N")
{
//do something...
}
}
The article in the comment may have been for WPF but the idea in it can still be used
Construct a class such as
public class MultiKeyGesture
{
private List<Keys> _keys;
private Keys _modifiers;
public MultiKeyGesture(IEnumerable<Keys> keys, Keys modifiers)
{
_keys = new List<Keys>(keys);
_modifiers = modifiers;
if (_keys.Count == 0)
{
throw new ArgumentException("At least one key must be specified.", "keys");
}
}
private int currentindex;
public bool Matches(KeyEventArgs e)
{
if (e.Modifiers == _modifiers && _keys[currentindex] == e.KeyCode)
//at least a partial match
currentindex++;
else
//No Match
currentindex = 0;
if (currentindex + 1 > _keys.Count)
{
//Matched last key
currentindex = 0;
return true;
}
return false;
}
}
but ignore the inheritance.
to use it
private MultiKeyGesture Shortcut1 = new MultiKeyGesture(new List<Keys> { Keys.A, Keys.B }, Keys.Control);
private MultiKeyGesture Shortcut2 = new MultiKeyGesture(new List<Keys> { Keys.C, Keys.D }, Keys.Control);
private MultiKeyGesture Shortcut3 = new MultiKeyGesture(new List<Keys> { Keys.E, Keys.F }, Keys.Control);
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
if (Shortcut1.Matches(e))
BackColor = Color.Green;
if (Shortcut2.Matches(e))
BackColor = Color.Blue;
if (Shortcut3.Matches(e))
BackColor = Color.Red;
}
If you only have a two key shortcut, like VS does, you could store the last key pressed in a variable.
private Keys lastKeyPressed = null;
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
if(e.Control && lastKeyPressed != null)
{
if(lastKeyPressed == Keys.firstKey && e.KeyCode == Keys.secondKey)
{
}
else if (...) // so on and so forth.
}
else if(e.Control)
lastKeyPressed = e.KeyCode;
}
protected override void OnKeyUp(KeyEventsArgs e)
{
if(!e.Control)
lastKeyPressed = null;
}
This would do a two key shortcut, and would reset it when the ctrl key is released. This is just untested pseudo code but its the concept of saving the last pressed key when Ctrl is being held then resetting it when ctrl is released that I'm trying to convey.
Call e.Modifiers for control key and e.KeyCode for the combined key.
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
// For Tow Key Shortcut.
if (e.Modifiers == Keys.Control && e.KeyCode == Keys.B)
{}
// For Triple Key Shortcut.
if (e.Modifiers.ToString() == (Keys.Shift+", "+Keys.Control) && e.KeyCode == Keys.B)
{}
}
// For Form level Key events you must have to set KeyPreview to True;
public Form1()
{
InitializeComponent();
this.KeyPreview = true;
}

Categories