Files
JRCookbook/JRCookbookControls/JRCookbookNumericTextBox.cs
2026-03-07 19:22:22 -06:00

159 lines
4.4 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace JRCookbookControls
{
[System.Serializable()]
public class JRCookbookNumericTextBox: TextBox
{
private String _strLastValue = String.Empty;
private bool _blnAllowNegative = true;
private bool _blnAllowDecimal = true;
private bool _blnAllowEmpty = true;
public JRCookbookNumericTextBox()
{
this.TextChanged += new System.EventHandler(this.NumericTextBox_TextChanged);
this.Validating += new System.ComponentModel.CancelEventHandler(this.NumericTextBox_Validating);
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public bool AllowDecimal
{
get
{
return _blnAllowDecimal;
}
set
{
_blnAllowDecimal = value;
}
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public bool AllowNegative
{
get
{
return _blnAllowNegative;
}
set
{
_blnAllowNegative = value;
}
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public bool AllowEmpty
{
get
{
return _blnAllowEmpty;
}
set
{
_blnAllowEmpty = value;
}
}
private void NumericTextBox_TextChanged(System.Object sender, System.EventArgs e)
{
bool blnValueIsOK = true;
Int32 intPosition = 0;
bool blnAlreadySeenDecimal = false;
//Allow digits, one decimal point, and minus sign (if first character only)
foreach (char chrCharacter in this.Text)
{
switch (chrCharacter)
{
case char x when (x >= '0' && x <= '9'):
//OK
break;
case '-':
if (intPosition > 0 || AllowNegative == false)
{
blnValueIsOK = false;
}
break;
case '.':
if (blnAlreadySeenDecimal)
{
blnValueIsOK = false;
}
else
{
blnAlreadySeenDecimal = true;
}
break;
default:
blnValueIsOK = false;
break;
}
intPosition += 1;
if (!blnValueIsOK)
{
break;
}
}
if (blnValueIsOK)
{
_strLastValue = this.Text;
}
else
{
Int32 oldSelectionStart = this.SelectionStart - 1;
this.Text = _strLastValue;
if (oldSelectionStart >= 0 && oldSelectionStart <= this.Text.Length)
{
this.SelectionStart = oldSelectionStart;
}
}
}
private void NumericTextBox_Validating(System.Object sender, System.ComponentModel.CancelEventArgs e)
{
if (this.Text == String.Empty)
{
if (AllowEmpty)
{
return;
}
else
{
e.Cancel = true;
}
}
//Now that we know it's not empty, make sure we have a digit
foreach (char chrCharacter in this.Text)
{
switch (chrCharacter)
{
case char x when (x >= '0' && x <= '9'):
//OK
return;
}
}
//If we got here, we have hyphen or period, but no digits
e.Cancel = true;
}
}
}