I have problem with my code , I want to replace specific string to a new one but it doesn't work
public void InsertYahoo(TextBox sender)
{
if (IsGmail(sender))
{
ReplaceGmail(sender);
}
else if(IsYahoo(sender))
{
return;
}
else
{
sender.Text +="#yahoo.com";
}
}
public bool IsYahoo(TextBox sender)
{
if (sender.Text.Contains("#yahoo.com")
{
return true;
}
else
{
return false;
}
}
public bool IsGmail(TextBox sender)
{
if (sender.Text.Contains("#gmail.com")
{
return true;
}
else
{
return false;
}
}
public void ReplaceGmail(TextBox sender)
{
sender.Text.Replace("#gmail.com, "#yahoo.com");
}
This code what i tried , so any suggestions?
Also I tried to get the index of #gmail.com and remove it but it did not work neither
Strings are immutable, so every method in the String class does not modify the current instance but returns a new one. You have to assign this to the original variable:
sender.Text = sender.Text.Replace("#gmail.com,"#yahoo.com");
If you are interested in why strings are immutable: Why .NET String is immutable?
Something like this:
//DONE: we should check for null
//DONE: it's Yahoo if it ends on #yahoo.com (not contains)
public static bool IsYahoo(TextBox sender) =>
sender != null &&
sender.Text.TrimEnd().EndsWith("#yahoo.com", StringComparison.OrdinalIgnoreCase);
public static bool IsGmail(TextBox sender) =>
sender != null &&
sender.Text.TrimEnd().EndsWith("#gmail.com", StringComparison.OrdinalIgnoreCase);
public static void InsertYahoo(TextBox sender) {
if (null == sender)
throw new ArgumentNullException(nameof(sender));
if (IsYahoo(sender))
return;
// Uncomment, In case you want to change gmail only
//if (!IsGmail(sender))
// return;
// If we have an eMail like bla-bla-bla#somewhere
int p = sender.Text.LastIndexOf('#');
// ... we change somewhere to yahoo.com
if (p > 0)
sender.Text = sender.Text.Substring(0, p) + "#yahoo.com";
}
Related
I'm stuck with some legacy code that I want to upgrade a bit. I want to change the way the ErrorProvider shows the error status on a Control. Default behavior is the Icon, and a ToolTip if you hover on the icon.
I would like to change this behavior to be more similar to what we use in our WPF controls. Which is a red back-color(Salmon pink) and the tool-tip on the control itself.
Any tips, links or some way forward
EDIT.
See my answer below, on what i ended up with.
ErrorProvider component doesn't support this feature and if you need it you can create it yourself.
You can subscribe to BindingComplete event of a BindingManagerBase and then you can use the event arg which is of type BindingCompleteEventArgs that contains some useful properties:
ErrorText to determine if there is an error in data-binding
Binding.Control to determine the control which is bounded to
These are enough for us to implement our solution.
Code
Here is a sample code which shows how can you handle BindingComplete event and use it to change BackColor and tool-tip of a control based on it's valid or invalid state.
Suppose you have a binding source, myBindingSource which is bound to a SampleModel class which is implemented IDataErrorInfo. You can subscribe to BindingComplete event of this.BindingContext[this.myBindingSource]:
private void Form1_Load(object sender, EventArgs e)
{
this.myBindingSource.DataSource = new SampleModel();
var bindingManager = this.BindingContext[this.myBindingSource];
bindingManager.BindingComplete += bindingManager_BindingComplete;
}
Dictionary<Control, Color> Items = new Dictionary<Control, Color>();
private void bindingManager_BindingComplete(object sender, BindingCompleteEventArgs e)
{
var control = e.Binding.Control;
//Store Original BackColor
if (!Items.ContainsKey(control))
Items[control] = control.BackColor;
//Check If there is an error
if (!string.IsNullOrEmpty(e.ErrorText))
{
control.BackColor = Color.Salmon;
this.errorToolTip.SetToolTip(control, e.ErrorText);
}
else
{
e.Binding.Control.BackColor = Items[e.Binding.Control];
this.errorToolTip.SetToolTip(control, null);
}
}
Thank you Reza Aghaei. This is what i came up with based on your comment and some additional searching... Some of this code comes from msdn resource
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Linq;
using System.Security.Permissions;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ErrorProvider
{
class BackgroundColorErrorProvider: Component, IExtenderProvider, ISupportInitialize
{
public BackgroundColorErrorProvider()
{
currentChanged = new EventHandler(ErrorManager_CurrentChanged);
}
public BackgroundColorErrorProvider(ContainerControl parentControl)
: this()
{
this.parentControl = parentControl;
propChangedEvent = new EventHandler(ParentControl_BindingContextChanged);
parentControl.BindingContextChanged += propChangedEvent;
}
public BackgroundColorErrorProvider(IContainer container)
: this()
{
if (container == null) {
throw new ArgumentNullException("container");
}
container.Add(this);
}
public bool CanExtend(object extendee)
{
return extendee is Control && !(extendee is Form) && !(extendee is ToolBar);
}
private bool inSetErrorManager = false;
private object dataSource;
private string dataMember = null;
private ContainerControl parentControl;
private BindingManagerBase errorManager;
private bool initializing;
private EventHandler currentChanged;
private EventHandler propChangedEvent;
private Dictionary<Control, Color> originalColor = new Dictionary<Control, Color>();
private Color errorBackgroundColor;
public ContainerControl ContainerControl
{
[UIPermission(SecurityAction.LinkDemand, Window = UIPermissionWindow.AllWindows)]
[UIPermission(SecurityAction.InheritanceDemand, Window = UIPermissionWindow.AllWindows)]
get
{
return parentControl;
}
set
{
if (parentControl != value)
{
if (parentControl != null)
parentControl.BindingContextChanged -= propChangedEvent;
parentControl = value;
if (parentControl != null)
parentControl.BindingContextChanged += propChangedEvent;
Set_ErrorManager(this.DataSource, this.DataMember, true);
}
}
}
public string DataMember
{
get { return dataMember; }
set
{
if (value == null) value = "";
Set_ErrorManager(this.DataSource, value, false);
}
}
public object DataSource
{
get { return dataSource; }
set
{
if ( parentControl != null && value != null && String.IsNullOrEmpty(this.dataMember))
{
// Let's check if the datamember exists in the new data source
try
{
errorManager = parentControl.BindingContext[value, this.dataMember];
}
catch (ArgumentException)
{
// The data member doesn't exist in the data source, so set it to null
this.dataMember = "";
}
}
Set_ErrorManager(value, this.DataMember, false);
}
}
public override ISite Site
{
set
{
base.Site = value;
if (value == null)
return;
IDesignerHost host = value.GetService(typeof(IDesignerHost)) as IDesignerHost;
if (host != null)
{
IComponent baseComp = host.RootComponent;
if (baseComp is ContainerControl)
{
this.ContainerControl = (ContainerControl)baseComp;
}
}
}
}
private ToolTip toolTip;
public ToolTip ToolTip
{
get { return toolTip; }
set { toolTip = value; }
}
public Color ErrorBackgroundColor
{
get { return errorBackgroundColor; }
set { errorBackgroundColor = value; }
}
private void Set_ErrorManager(object newDataSource, string newDataMember, bool force)
{
if (inSetErrorManager)
return;
inSetErrorManager = true;
try
{
bool dataSourceChanged = this.DataSource != newDataSource;
bool dataMemberChanged = this.DataMember != newDataMember;
//if nothing changed, then do not do any work
//
if (!dataSourceChanged && !dataMemberChanged && !force)
{
return;
}
// set the dataSource and the dataMember
//
this.dataSource = newDataSource;
this.dataMember = newDataMember;
if (!initializing)
{
UnwireEvents(errorManager);
// get the new errorManager
//
if (parentControl != null && this.dataSource != null && parentControl.BindingContext != null)
{
errorManager = parentControl.BindingContext[this.dataSource, this.dataMember];
}
else
{
errorManager = null;
}
// wire the events
//
WireEvents(errorManager);
// see if there are errors at the current
// item in the list, w/o waiting for the position to change
if (errorManager != null)
UpdateBinding();
}
}
finally
{
inSetErrorManager = false;
}
}
public void UpdateBinding()
{
ErrorManager_CurrentChanged(errorManager, EventArgs.Empty);
}
private void UnwireEvents(BindingManagerBase listManager)
{
if (listManager != null)
{
listManager.CurrentChanged -= currentChanged;
listManager.BindingComplete -= new BindingCompleteEventHandler(this.ErrorManager_BindingComplete);
CurrencyManager currManager = listManager as CurrencyManager;
if (currManager != null)
{
currManager.ItemChanged -= new ItemChangedEventHandler(this.ErrorManager_ItemChanged);
currManager.Bindings.CollectionChanged -= new CollectionChangeEventHandler(this.ErrorManager_BindingsChanged);
}
}
}
private void WireEvents(BindingManagerBase listManager)
{
if (listManager != null)
{
listManager.CurrentChanged += currentChanged;
listManager.BindingComplete += new BindingCompleteEventHandler(this.ErrorManager_BindingComplete);
CurrencyManager currManager = listManager as CurrencyManager;
if (currManager != null)
{
currManager.ItemChanged += new ItemChangedEventHandler(this.ErrorManager_ItemChanged);
currManager.Bindings.CollectionChanged += new CollectionChangeEventHandler(this.ErrorManager_BindingsChanged);
}
}
}
private void ErrorManager_BindingsChanged(object sender, CollectionChangeEventArgs e)
{
ErrorManager_CurrentChanged(errorManager, e);
}
private void ParentControl_BindingContextChanged(object sender, EventArgs e)
{
Set_ErrorManager(this.DataSource, this.DataMember, true);
}
private void ErrorManager_ItemChanged(object sender, ItemChangedEventArgs e)
{
BindingsCollection errBindings = errorManager.Bindings;
int bindingsCount = errBindings.Count;
// If the list became empty then reset the errors
if (e.Index == -1 && errorManager.Count == 0)
{
for (int j = 0; j < bindingsCount; j++)
{
if ((errBindings[j].Control != null))
{
// ...ignore everything but bindings to Controls
SetError(errBindings[j].Control, "");
}
}
}
else
{
ErrorManager_CurrentChanged(sender, e);
}
}
private void SetError(Control control, string p)
{
if (String.IsNullOrEmpty(p))
{
if (originalColor.ContainsKey(control))
control.BackColor = originalColor[control];
toolTip.SetToolTip(control, null);
}
else
{
control.BackColor = ErrorBackgroundColor;
toolTip.SetToolTip(control, p);
}
}
private void ErrorManager_BindingComplete(object sender, BindingCompleteEventArgs e)
{
Binding binding = e.Binding;
if (binding != null && binding.Control != null)
{
SetError(binding.Control, (e.ErrorText == null ? String.Empty : e.ErrorText));
}
}
private void ErrorManager_CurrentChanged(object sender, EventArgs e)
{
if (errorManager.Count == 0)
{
return;
}
object value = errorManager.Current;
if (!(value is IDataErrorInfo))
{
return;
}
BindingsCollection errBindings = errorManager.Bindings;
int bindingsCount = errBindings.Count;
// We can only show one error per control, so we will build up a string...
//
Hashtable controlError = new Hashtable(bindingsCount);
for (int j = 0; j < bindingsCount; j++)
{
// Ignore everything but bindings to Controls
if (errBindings[j].Control == null)
{
continue;
}
string error = ((IDataErrorInfo)value)[errBindings[j].BindingMemberInfo.BindingField];
if (error == null)
{
error = "";
}
string outputError = "";
if (controlError.Contains(errBindings[j].Control))
outputError = (string)controlError[errBindings[j].Control];
// VSWhidbey 106890: Utilize the error string without including the field name.
if (String.IsNullOrEmpty(outputError))
{
outputError = error;
}
else
{
outputError = string.Concat(outputError, "\r\n", error);
}
controlError[errBindings[j].Control] = outputError;
}
IEnumerator enumerator = controlError.GetEnumerator();
while (enumerator.MoveNext())
{
DictionaryEntry entry = (DictionaryEntry)enumerator.Current;
SetError((Control)entry.Key, (string)entry.Value);
}
}
public void BeginInit()
{
initializing = true;
}
public void EndInit()
{
initializing = false;
Set_ErrorManager(this.DataSource, this.DataMember, true);
}
}
}
I'm trying to add copy/paste feature to my WPF application. I have a DataGrid which I allowed to select an entire row. A row is an object of type AcquisitionParameters. The selection is ok, the copy to clipboard too. After copying to clipboard, I verify if the data has been well serialized and it is the case. But when I try to retrieve the object from clipboard, I am not able to deserialize it on its original format, but in a CSV format.
private void dataGridAcquisitions_CopyingRowClipboardContent(object sender, DataGridRowClipboardEventArgs e)
{
System.Windows.Clipboard.Clear();
DataFormat format = System.Windows.DataFormats.GetDataFormat(typeof(AcquisitionParameters).FullName);
System.Windows.IDataObject dataObj = new System.Windows.DataObject();
dataObj.SetData(format.Name, (AcquisitionParameters)e.Item, false);
System.Windows.Clipboard.SetDataObject(dataObj, true);
bool ispresent = dataObj.GetDataPresent(format.Name); // ok
AcquisitionParameters parameters = dataObj.GetData(format.Name) as AcquisitionParameters; //ok
if(parameters != null && ispresent)
{
//enter here
}
}
private void dataGridAcquisitions_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
if (e.Key == Key.V && (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
{
System.Windows.IDataObject dataObj = System.Windows.Clipboard.GetDataObject(); //type of AcquisitionParameters not available, only HTML, CSV, etc.
string format = typeof(AcquisitionParameters).FullName;
if(dataObj.GetDataPresent(format)) //false
{
AcquisitionParameters parameters = dataObj.GetData(format) as AcquisitionParameters;
if(parameters != null)
{
}
}
}
}
And the declaration of my AcquisitionParameters class
namespace App
{
[Serializable]
public class AcquisitionParameters
{
private double pulse;
public double Pulse
{
get { return pulse; }
set { pulse = value; }
}
private double range;
public double Range
{
get { return range; }
set { range = value; }
}
private double offset;
public double Offset
{
get { return offset; }
set { offset = value; }
}
}
}
Try accessing the data from the Clipboard like this:
object data = Clipboard.GetData("AcquisitionParameters");
if (data != null) return (AcquisitionParameters)data;
return new AcquisitionParameters();
UPDATE >>>
If that doesn't help, then try setting the data like this:
DataObject dataObject = new DataObject();
dataObject.SetData("AcquisitionParameters", (AcquisitionParameters)e.Item, false);
Clipboard.SetDataObject(dataObject);
I've made a document class that downloads and reads the text in it. The smart thing is that it only downloads and reads the text in the document when or if it's needed. By using the Text property it'll try to read the document, if it hasn't been downloaded it'll download it then read it.
It's very nice. However I've noticed my use of Exceptions leads to some funky code. See below.
Document class
public delegate byte[] DownloadBinaryDelegate(IDocument document);
public delegate string TextReaderDelegate(IDocument document);
public class Document
{
public DownloadBinaryDelegate DownloadBinaryDelegate { private get; set; }
public TextReaderDelegate TextReaderDelegate { private get; set; }
private bool _binaryIsSet;
private byte[] _binary;
public byte[] Binary
{
get
{
if (_binaryIsSet)
return _binary;
if (DownloadBinaryDelegate == null)
throw new NullReferenceException("No delegate attached to DownloadBinaryDelegate.");
Binary = DownloadBinaryDelegate(this);
DownloadBinaryDelegate = null; // unhock delegate as it's no longer needed.
return _binary;
}
set
{
if (_binaryIsSet)
return;
_binary = value;
_binaryIsSet = true;
}
}
private bool _textIsSet;
private string _text;
public string Text
{
get
{
if (_textIsSet)
return _text;
if (TextReaderDelegate == null)
throw new NullReferenceException("No delegate attached to TextReaderDelegate.");
Text = TextReaderDelegate(this); // this delegate will call Binary and return the translated text.
TextReaderDelegate = null; // unhock delegate as it's no longer needed.
return _text;
}
set
{
if (_textIsSet)
return;
_text = value;
_textIsSet = true;
}
}
The Problem
What I wrote in the first place.
if (document.Text == null) // text is not set
{
if (document.Binary == null) // binary has not been downloaded
document.DownloadBinaryDelegate = Util.DownloadDocument;
document.TextReaderDelegate = Util.ReadDocument;
}
Totally forgetting that the Text property throws an exception.
So I have to write something like this, which is a bit funky code.
// check if text has already been read and set
try
{
var isTextSet = document.Text == null;
}
catch (NullReferenceException)
{
document.DownloadBinaryDelegate = Util.DownloadDocument;
document.TextReaderDelegate = Util.ReadDocument;
}
I hope you can see what I mean.
So my question, is this a bad design? How would you have done it? Keep in mind I would still like the current functionality.
Lazy initialization is already baked into the .NET framework. I would suggest re-implementing your class using Lazy<T>.
To answer your specific question, it sounds like your class will always require the Binary and Text delegates, so I would make them required parameters to the constructor.
I was unable to use Lazy as I'm using delegate(this) which is not allowed.
So I ended up using the fine answer from here: What exception type to use when a property cannot be null?
public class Document
{
private DownloadBinaryDelegate _downloadBinaryDelegate;
public void SetDownloadBinaryDelegate(DownloadBinaryDelegate downloadBinary)
{
if (downloadBinary == null)
throw new ArgumentNullException("downloadBinary");
_downloadBinaryDelegate = downloadBinary;
}
private TextReaderDelegate _textReaderDelegate;
public void SetTextReaderDelegate(TextReaderDelegate readerDelegate)
{
if (readerDelegate == null)
throw new ArgumentNullException("readerDelegate");
_textReaderDelegate = readerDelegate;
}
private bool _binaryIsSet;
private byte[] _bytes;
public void SetBinary(byte[] bytes, bool forceOverwrite = false)
{
if (_binaryIsSet && !forceOverwrite)
return;
_bytes = bytes;
_binaryIsSet = true;
}
public byte[] GetBinary()
{
if (_binaryIsSet)
return _bytes;
if (_downloadBinaryDelegate == null)
throw new InvalidOperationException("No delegate attached to DownloadBinaryDelegate. Use SetDownloadBinaryDelegate.");
SetBinary(_downloadBinaryDelegate(this));
_downloadBinaryDelegate = null; // unhock delegate as it's no longer needed.
return _bytes;
}
public bool TryGetBinary(out byte[] bytes)
{
if (_binaryIsSet)
{
bytes = _bytes;
return true;
}
if (_downloadBinaryDelegate != null)
{
bytes = GetBinary(); // is this legit?
return true;
}
bytes = null;
return false;
}
private bool _textIsSet;
private string _text;
public void SetText(string text, bool forceOverwrite = false)
{
if (_textIsSet && !forceOverwrite)
return;
_text = text;
_textIsSet = true;
}
public string GetText()
{
if (_textIsSet)
return _text;
if (_textReaderDelegate == null)
throw new InvalidOperationException("No delegate attached to TextReaderDelegate. Use SetTextReaderDelegate.");
SetText(_textReaderDelegate(this)); // this delegate will call Binary and return the read text.
_textReaderDelegate = null; // unhock delegate as it's no longer needed.
return _text;
}
public bool TryGetText(out string text)
{
byte[] bytes;
if (!TryGetBinary(out bytes))
{
text = null;
return false;
}
if (_textIsSet)
{
text = _text;
return true;
}
if (_textReaderDelegate != null)
{
text = GetText(); // is this legit?
return true;
}
text = null;
return false;
}
}
CircuitBoard vBoard = this;
// Find the desired circuit shape
CircuitShape vShape = vBoard.GetComponent(vId);
In the above statement the vBoard is throwing null in certain time. Any idea?
Please help.
Thank you in advance....
more code.. this is a public function
class CircuitBoard :Canvas
{
public void Move(string iBoardId, string iCircuitShapeId, double iXCordinate, double iYCordinate)
{
CircuitBoard vBoard = this;
// secutity check..
if (null != vBoard)
{
string vId = PCBFactory.GetUniqueTag(iCircuitShapeId, vBoard);
// Find the desired circuit shape
CircuitShape vShape = vBoard.GetComponent(vId);
if (vShape != null)
{
// do something...
}
}
}
}
Why are you assigning this to something in the first place? Why not just try:
class CircuitBoard :Canvas
{
public void Move(string iBoardId, string iCircuitShapeId, double iXCordinate, double iYCordinate)
{
string vId = PCBFactory.GetUniqueTag(iCircuitShapeId, vBoard);
CircuitShape vShape = this.GetComponent(vId);
if (vShape != null)
{
// do something...
}
}
}
}
There's no need to define vBoard at all.
This is probably a long shot, but I'm trying to minimize the repition in the program I'm working on, and have run into a snag. As can be seen in the ClearTextBoxes() method below, I have a very repetitive bit of code that I would prefer to place inside a foreach loop for succinctness. (Originally the foreach (object box in customBoxes) loop was not there). I tried to do this with the following List, but to no avail. I'm not sure if this is just not possible to do, or if I'm simply doing it wrong. I would appreciate any help you could give, and if this can't be done, then how can I shrink this code block?
Thanks!
List<object> customBoxes = new List<object>();
customBoxes.AddRange(new[] { "TextBox", "DateBox", "DigitBox", "PhoneBox", "WaterTextBox" });
public void ClearTextBoxes()
{
ChildControls ccChildren = new ChildControls();
foreach (object o in ccChildren.GetChildren(rvraDockPanel, 2))
{
foreach (object box in customBoxes)
{
if (o.GetType() == typeof(TextBox))
{
TextBox txt = (TextBox)o;
txt.Text = "";
}
if (o.GetType() == typeof(DigitBox))
{
DigitBox digit = (DigitBox)o;
digit.Text = "";
}
if (o.GetType() == typeof(PhoneBox))
{
PhoneBox phone = (PhoneBox)o;
phone.Text = "";
}
if (o.GetType() == typeof(DateBox))
{
DateBox date = (DateBox)o;
date.Text = "";
}
if (o.GetType() == typeof(WatermarkTextBox))
{
WatermarkTextBox water = (WatermarkTextBox)o;
water.Text = "";
}
}
}
}
List<Type> customBoxes = new List<Type>();
customBoxes.AddRange(new[] { typeof(PhoneBox), typeof(DigitBox), ....." });
foreach (Control c in this.Controls)
{
if (customBoxes.Contains(c.GetType()))
{
c.Text = string.Empty;
}
}
I would create an interface with a ClearText() method.
interface IClearable
{
public void ClearText();
}
Then you can inherit from each control and apply that interface:
class ClearableDigitBox : DigitBox, IClearable
{
public void ClearText() {
Text = String.Empty;
}
}
// etc...
So it's just:
var list = new List<IClearable>;
// ...
foreach (IClearable control in list) control.ClearText();
You could use reflection in some way to mimic some ductyping behavior but i wouldnt go for that solution since it's not performant and ugly.
foreach (object box in customBoxes)
{
var boxType = box.GetType();
var textProperty = boxType.GetProperty("Text");
if (textProperty != null && textProperty.CanWrite)
{
textProperty.SetValue(box, "", null);
}
}
Or you can use dynamic to achieve the same result:
foreach (dynamic box in customBoxes)
{
box.Text = "";
}
The way to go would be to make your custom controls implement a single interface IWithTextProperty which ofcourse exposes the text property.
Aren't all the input boxes a part of Control object?
if so, and you want to clear all the text from the controls
then i would probably have a method like:
public void ClearText(List<Control> items)
{
foreach (Control control in items)
{
control.Text = string.Empty;
}
}
if you just want to locate controls of a specific type
public void ClearText(List<Control> items)
{
foreach (Control control in items)
{
if (control is TextBox)
((TextBox)control).Text = string.Empty;
else if (control is DigitBox)
((DigitBox)control).Text = string.Empty;
else
{ // Handle anything else.}
}
}
In response to a couple of the replies so far, this is the class file I have for the custom boxes. The NumberTextBox class is the default snippet that VS added. I haven't used it, just haven't deleted it either. In addition to the DateBox(which is collapsed to save space) class, there is also a PhoneBox class that inherits from DigitBox as well. the WatermarkTextBox class that DigitBox inherits from is in the WpfToolkit.Extended.dll. The only real difference in these classes is that each adds a method to allow/disallow formatting keys being pressed (parenthesis, periods, hyphens, etc).
This class basically came about as a result of trying to merge several different snippets I found around the web, but the purpose of these boxes is to enable a watermark and also restrict the characters that can be entered into those boxes.
public class NumberTextBox : Control
{
static NumberTextBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(NumberTextBox), new FrameworkPropertyMetadata(typeof(NumberTextBox)));
}
}
public class DigitBox : WatermarkTextBox, IClearable
{
#region Constructors
///<summary>
///The default constructor
/// </summary>
public DigitBox()
{
TextChanged += new TextChangedEventHandler(OnTextChanged);
KeyDown += new KeyEventHandler(OnKeyDown);
PreviewKeyDown += new KeyEventHandler(OnPreviewDown);
}
#endregion
#region Properties
new public String Text
{
get { return base.Text; }
set
{
base.Text = LeaveOnlyNumbers(value);
}
}
#endregion
#region Functions
public bool IsNumberKey(Key inKey)
{
if (inKey < Key.D0 || inKey > Key.D9)
{
if (inKey < Key.NumPad0 || inKey > Key.NumPad9)
{
return false;
}
}
return true;
}
public bool IsActionKey(Key inKey)
{
return inKey == Key.Delete || inKey == Key.Back || inKey == Key.Tab || inKey == Key.Return;
}
public string LeaveOnlyNumbers(String inString)
{
String tmp = inString;
foreach (char c in inString.ToCharArray())
{
if (!IsDigit(c))
{
tmp = tmp.Replace(c.ToString(), "");
}
}
return tmp;
}
public bool IsSpaceKey(Key inKey)
{
if (inKey == Key.Space)
{
return true;
}
return false;
}
public bool IsDigit(char c)
{
return (c >= '0' || c <='9');
}
#endregion
#region Event Functions
protected virtual void OnKeyDown(object sender, KeyEventArgs e)
{
e.Handled = !IsNumberKey(e.Key) && !IsActionKey(e.Key) && !IsSpaceKey(e.Key);
}
protected virtual void OnTextChanged(object sender, TextChangedEventArgs e)
{
base.Text = LeaveOnlyNumbers(Text);
}
protected virtual void OnPreviewDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Space)
{
e.Handled = true;
}
}
#endregion
}
public class DateBox : DigitBox