WinForms - MaskedTextBox - "variable-width" masking possible? - c#

I need to create a WinForms textbox that allows decimal text exclusive-or integer text. Also, I don't wish to be required to specify the length of the text in the mask; the user should be able to enter as many characters as he wants, as long as the text fits the decimal or integer mold. However, the MaskedTextBox doesn't allow variable-length masking, as far as I know; I can't find a pre-existing control that does this, either.
Advice? I suppose I could inherit TextBox, override OnKeyPress and do the work there, but I don't know whether a pre-existing control would do things more gracefully.

the NumericUpDown control has some built in decimal/integer parsing behavior - sounds like it might be what you're looking for. Of course, you end up with the updown controls on the text box too.

Try this:
private void TextBox1_Validating(object sender, EventArgs e)
{
string expression = "^\d{1,8}(\.\d{2,2})?$";
if (System.Text.RegularExpressions.Regex.Match(this.txt_monto_total.Text, expression).Success)
this.label_total.Visible = false;
else
this.label_total.Visible = true;
}
It's not a mask but it will let you tell the user if they have entered an incorrect format (i do it by showing the label), you can use any regular expression, in my case i only want numbers with 1 or 8 digits before the "." and 2 after it.

Here's a solution. It's not perfect - it may eat control characters in certain cases, and it doesn't cleanly handle pasting - but it works well enough!
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
namespace WinFormsTest
{
public partial class MaskedTextBox : TextBox
{
public enum EntryTypeEnum
{
Any,
Integer,
Decimal
}
[DefaultValue(EntryTypeEnum.Any)]
public EntryTypeEnum EntryType { get; set; }
public MaskedTextBox()
{
InitializeComponent();
}
protected override void OnKeyPress(KeyPressEventArgs e)
{
var keyIsValid =
(EntryType == EntryTypeEnum.Any)
|| char.IsControl(e.KeyChar)
|| isValid(Text + e.KeyChar);
e.Handled = !keyIsValid;
base.OnKeyPress(e);
}
protected override void OnValidating(CancelEventArgs e)
{
e.Cancel = !isValid(Text);
base.OnValidating(e);
}
protected bool isValid(string textToValidate)
{
switch (EntryType)
{
case EntryTypeEnum.Any:
break;
case EntryTypeEnum.Decimal:
{
decimal result;
if (!decimal.TryParse(textToValidate, out result))
{
return false;
}
}
break;
case EntryTypeEnum.Integer:
{
int result;
if (!int.TryParse(textToValidate, out result))
{
return false;
}
}
break;
}
return true;
}
}
}

After much searching I was able to discover a control on codeproject that allows for a variable length number.
It is the Nullable Masked Edit, and a Better Masked Edit Also! project.
Note you need to use the 'EditMask' field to set the Mask properties. Trying to set the 'Mask' field won't work.
I was able to set a mask of 999.9 and then entering 1.1 would work without having to add leading spaces.

Related

How to disable / cancel undo button in xamarin

I am creating an application that has an entry. I am trying to restrict the entry to only allow for numeric input. I have already tried using Keyboard = "Numeric". For the iPad, however, the keyboard has more characters than just numbers. So I had to restrict what is entered. When I do this however, if the user types in a parenthesis, for example, it does stop the character from being entered. But then if the user presses undo, it crashes. I assume this is because the software keyboard is separate from the app, so it is looking for that parenthesis character, but it isn't there. Here is my code:
private void Entry_TextChanged(object sender, TextChangedEventArgs e)
{
Entry theEntry = (Entry)sender;
string entryText = theEntry.Text;
if(entryText != null && entryText.Length != 0)
{
char theMostRecentInput = entryText[entryText.Length - 1];
if(!Extension.IsNumeric(theMostRecentInput))
{
theEntry.TextChanged -= Entry_TextChanged;
theEntry.Text = e.OldTextValue;
theEntry.TextChanged += Entry_TextChanged;
}
}
}
Thanks for the help!
This issue will occur when Validation like special character, Max Limit, etc... for Input field are implemented.
By that time undo action will have extra character count than current input field text characters length in iOS ShouldChangeCharacters Delegate. This leads to app crash.
One of the solution is to return as false in such scenario instead of disabling undo buttons. Below solution worked for me.
public class ExtEntryRenderer : EntryRenderer
{
protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (Control != null)
{
Control.ShouldChangeCharacters += (UITextField textField, NSRange range, string replacementString) =>
{
if (range.Location + range.Length > ((UITextField)textField).Text.Length)
return false;
return true;
};
}
}
}
I would do this in a Entry custom renderer that way you you can control the input via ShouldChangeCharacters and not have to kludge it by allowing the input and then having to remove the handler and change the text back to the old value...
Here is a quick example that allows numeric, It also automatically handles clipboard pasting non-numeric strings as those would be disallowed. I am using the NSCharacterSet.DecimalDigits character set as that would be internationalized by the OS, but you could allow/disallow any chars of your choosing.
You could also include haptic, visual or audio feedback on the disallowed/rejected entries...
[assembly: ExportRenderer(typeof(NumericEntry), typeof(NumericEntryRenderer))]
namespace Forms_PCL_Tester.iOS
{
public class NumericEntryRenderer : EntryRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Entry> e)
{
base.OnElementChanged(e);
if (e.NewElement != e.OldElement)
if (Control != null)
{
Control.KeyboardType = UIKeyboardType.NumbersAndPunctuation;
Control.ShouldChangeCharacters += (UITextField textField, NSRange range, string replacementString) =>
{
foreach (var aChar in replacementString)
if (!NSCharacterSet.DecimalDigits.Contains(aChar))
return false;
return true;
};
}
}
}
}

Creating Calculator with Class - C#, However unable to solve error

I'm trying to create a Calculator with a Class. However using references from the internet particularly from this website (https://www.sourcecodester.com/tutorials/c/7548/simple-calculator-using-class-c.html)
It did not mention to declare "Information" or whatsoever.
When I typed in the code, the error list return with Information does not exist in current context.
Is there a way to modify the code below? Thank you so much.
public partial class Form4 : Form
{
public Form4()
{
InitializeComponent();
}
private void Form4_Load(object sender, EventArgs e)
{
}
public void RadioButton_Click(object sender, System.EventArgs e)
{
//call a constructor method and return to cal as an instance of a class
calculate cal = new calculate();
//declaring the string variable represent as a textbox
string txtnum1 = TextBox1.Text;
string txtnum2 = TextBox2.Text;
//declaring the double variable
double dbl_val1 = default(double);
double dbl_val2 = default(double);
if (**Information**.IsNumeric(txtnum1) && **Information**.IsNumeric(txtnum2)) //check if the textbox has a numeric value
{
//convert the string to double
dbl_val1 = double.Parse(txtnum1);
dbl_val2 = double.Parse(txtnum2);
//get the value of the converted variable
//to pass it into the variable in the class
cal.num1 = dbl_val1;
cal.num2 = dbl_val2;
//the condition is, if the radiobutton is clicked,
//the operation of MDAS executes.
if (Radio_Multiplication.Checked)
{
//result:
cal.multiply(); //call a subname in a class for multiplying
}
else if (Radio_Addition.Checked)
{
//result:
cal.add(); //call a subname in a class for adding
}
else if (Radio_Subtraction.Checked)
{
//result:
cal.subtract(); //call a subname in a class for subtracting
}
}
else
{
//the result is:
//if the textbox is empty or has a string value
TextBox3.Text = "Enter a number";
return;
}
//put the result of the MDAS to a textbox.
TextBox3.Text = cal.total.ToString();
}
}
I had a quick look at the link and they don't appear to have declared Information anywhere nor have they indicated that they've overridden anything so...I don't know.
That line, however, is just validating that the information entered into the two text boxes are actually numbers and not anything else that can't be calculated.
There are lots of methods you could use to check those numbers. Options would include, but are not limited to:
if(Int32.TryParse(txtNum1, out int temp1) && Int32.TryParse(txtNum2, out int temp2))
{
do stuff;
}
or
if(txtNum1.All(char.IsDigit) && txtNum2.All(char.IsDigit))
{
do stuff;
}
There are other options, but those two might be worth looking into.
Downloading the sample project, I had a look at what Information refers to. Turns out, it's a class from the Microsoft.VisualBasic namespace, presumably for exposing certain aspects of the VB core library to all .NET languages. You can use it in your program by adding a reference to Microsoft.VisualBasic to your project and adding:
using Microsoft.VisualBasic;
to the top of your code file.
(Personally, I can't imagine that this approach is terribly efficient. It's supposed to take an object and determine if it can be evaluated as a number, and I have no idea what approaches it uses to make that deduction based on any random object. You would probably be better off using one of the alternatives that Benny O'Neill suggests.)

Where to declare variables in C#

I have created a simple calculator using VS 2013 Pro... and here is the segment of the codes:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace CalcTwo
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
string input = string.Empty;
double numb1, numb2, result;
private void button1_Click(object sender, EventArgs e)
{
double.TryParse(textBox1.Text, out numb1);
double.TryParse(textBox2.Text, out numb2);
result = numb1 + numb2;
textBox3.Text = result.ToString();
}
private void button4_Click(object sender, EventArgs e)
{
double.TryParse(textBox1.Text, out numb1);
double.TryParse(textBox2.Text, out numb2);
result = numb1 - numb2;
textBox3.Text = result.ToString();
}
}
}
now the problem I'm facing is, I've got two more buttons for multiplying and dividing, which in turn forces me to copy paste
double.TryParse(textBox1.Text, out numb1);
double.TryParse(textBox2.Text, out numb2);
for each button. I tried to put the codes with the other variables(double numb1, numb2, result) but getting an error...
Here is the screenshots
Pretty new to Visual Studio and C#.
Help is appreciated! :)
The declaration of the variables is fine at the class level. However, in order to reduce the code duplication you can extract that specific functionality into its own method. Something like this perhaps:
private void CaptureValues()
{
double.TryParse(textBox1.Text, out numb1);
double.TryParse(textBox2.Text, out numb2);
}
Then in the handlers:
private void button1_Click(object sender, EventArgs e)
{
CaptureValues();
result = numb1 + numb2;
textBox3.Text = result.ToString();
}
This gives you a convenient place to put additional code. Checking the inputs and displaying a message, for example:
private void CaptureValues()
{
if (!double.TryParse(textBox1.Text, out numb1))
// textBox1 couldn't be parsed, show an error message
if (!double.TryParse(textBox2.Text, out numb2))
// textBox2 couldn't be parsed, show an error message
}
You could even go a step further and put the values into class-level properties. Something like this:
private double Value1
{
get
{
double result;
if (!double.TryParse(textBox1.Text, out result))
throw new Exception("Couldn't parse the first text box!");
return result;
}
}
private double Value2
{
get
{
double result;
if (!double.TryParse(textBox2.Text, out result))
throw new Exception("Couldn't parse the second text box!");
return result;
}
}
With those, you don't need your numb1 or numb2 variables at all, just reference the properties directly:
textBox3.Text = (Value1 + Value2).ToString();
Currently the properties can throw exceptions, so you might want to handle that:
try
{
textBox3.Text = (Value1 + Value2).ToString();
}
catch (Exception ex)
{
// examine what happened with ex and show an error
}
You can throw a more specific Exception type of course, even a custom one. Or you can respond to the error in the properties instead of in the handlers and not use exceptions at all. (There's an argument to be made, and I agree with it, never to use exceptions for normal logic, and this is potentially one of those edge cases. If it's normal logic, don't use exceptions. If it's an exceptional case and the value should never be un-parseable, go ahead and use them. I'd prefer not to in this case, but was just adding it as a possibility.)
There are a lot of options.

TryParse C# Visual Studio

Can someone explain how to use TryParse in C# Visual Studio to validate some textbox. I need a function using TryParse, I have an idea but it's not working
public void Letra(TextBox caja)
{
char valor;
if(char.TryParse(caja.Text, out valor))
{
if (caja.TextLength>1)
{
caja.Text = caja.Text.Remove(caja.TextLength);
caja.SelectionStart = caja.TextLength;
}
}
}
Please see the code below.
Please note, using Javascript this could be done a lot better, but since you really want a C# function, here it is.
public bool isValid(TextBox caja)
{
string sTemp;
if (caja != null)
{
sTemp = caja.Text;
}
else
{
return false;
}
if (sTemp.Length > 0)
{
foreach (char cTemp in sTemp)
{
if (char.IsNumber(cTemp))
{
return false;
}
}
}
else
{
return false;
}
return true;
}
Regards
You can always use Regular Expression for such type of validation. It is best practice and pretty fast-
Regex charOnly=new Regex("^[^0-9]$");
You can use it in C# as you want and if your TestBox is in web form then use RegularExpressionValidator. You should refer How can I get a regex to check that a string only contains alpha characters [a-z] or [A-Z]?
You can check if your string contains numbers with following method
private bool CheckIfTextContainsNumber(string TextToCheck)
{
return Regex.IsMatch(TextToCheck, #"\d");
}
\d stands for digit (0-9) + other digits e.g. arabic
Further you code create a textbox in which you cannot type in kind of numbers by creating an EventHandler which catches the KeyPress-Event.
YourTextBoxControl.KeyPress += YourTextBoxControl_KeyPress;
Here you can check whether the char typed in is a number. If the char is a number then you set Handled to true
private void YourTextBoxControl_KeyPress(object sender, KeyPressEventArgs e)
{
e.Handled = Char.IsNumber(e.KeyChar);
}

Looking for a simple C# numeric edit control

I am a MFC programmer who is new to C# and am looking for a simple control that will allow number entry and range validation.
Look at the "NumericUpDown" control. It has range validation, the input will always be numeric, and it has those nifty increment/decrement buttons.
I had to implement a Control which only accepted numbers, integers or reals.
I build the control as a specialization of (read: derived from) TextBox control, and using input control and a regular expresión for the validation.
Adding range validation is terribly easy.
This is the code for building the regex. _numericSeparation is a string with characters accepted as decimal comma values
(for example, a '.' or a ',': $10.50 10,50€
private string ComputeRegexPattern()
{
StringBuilder builder = new StringBuilder();
if (this._forcePositives)
{
builder.Append("([+]|[-])?");
}
builder.Append(#"[\d]*((");
if (!this._useIntegers)
{
for (int i = 0; i < this._numericSeparator.Length; i++)
{
builder.Append("[").Append(this._numericSeparator[i]).Append("]");
if ((this._numericSeparator.Length > 0) && (i != (this._numericSeparator.Length - 1)))
{
builder.Append("|");
}
}
}
builder.Append(#")[\d]*)?");
return builder.ToString();
}
The regular expression matches any number (i.e. any string with numeric characters) with only one character as a numeric separation, and a '+' or a '-' optional character at the beginning of the string.
Once you create the regex (when instanciating the Control), you check if the value is correct overriding the OnValidating method.
CheckValidNumber() just applies the Regex to the introduced text. If the regex match fails, activates an error provider with an specified error (set with ValidationError public property) and raises a ValidationError event.
Here you could do the verification to know if the number is in the requiered range.
private bool CheckValidNumber()
{
if (Regex.Match(this.Text, this.RegexPattern).Value != this.Text)
{
this._errorProvider.SetError(this, this.ValidationError);
return false;
}
this._errorProvider.Clear();
return true;
}
protected override void OnValidating(CancelEventArgs e)
{
bool flag = this.CheckValidNumber();
if (!flag)
{
e.Cancel = true;
this.Text = "0";
}
base.OnValidating(e);
if (!flag)
{
this.ValidationFail(this, EventArgs.Empty);
}
}
As I said, i also prevent the user from input data in the text box other than numeric characteres overriding the OnKeyPress methdod:
protected override void OnKeyPress(KeyPressEventArgs e)
{
if ((!char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar)) && (!this._numberSymbols.Contains(e.KeyChar.ToString()) && !this._numericSeparator.Contains(e.KeyChar.ToString())))
{
e.Handled = true;
}
if (this._numberSymbols.Contains(e.KeyChar.ToString()) && !this._forcePositives)
{
e.Handled = true;
}
if (this._numericSeparator.Contains(e.KeyChar.ToString()) && this._useIntegers)
{
e.Handled = true;
}
base.OnKeyPress(e);
}
The elegant touch: I check if the number valid every time the user releases a key, so the user can get feedback as he/she types. (But remember that you must be carefull with the ValidationFail event ;))
protected override void OnKeyUp(KeyEventArgs e)
{
this.CheckValidNumber();
base.OnKeyUp(e);
}
You can use a regular textbox and a Validator control to control input.
Try using an error provider control to validate the textbox. You can use int.TryParse() or double.TryParse() to check if it's numeric and then validate the range.
You can use a combination of the RequiredFieldValidator and CompareValidator (Set to DataTypeCheck for the operator and Type set to Integer)
That will get it with a normal textbox if you would like, otherwise the recommendation above is good.

Categories