I want every time that TextBox filed is set the back color change according to the sign.
public TextBox Current_value_text1
{
get { return Current_value_text; }
set {
Current_value_text = value;
if (Current_value_text.Text[0] == '+')
Current_value_text.BackColor = Color.Green;
else
Current_value_text.BackColor = Color.Red;
}
}
but I want to do this for all my textbox fields - any suggestions?
Thanks
You are probably looking for TextChanged event: whenever TextBox(es) change its Text, analyze it and update BackColor when necessary.
If it's your case, can select all the Textboxes (say, with a mouse), open "Properties" window and implement event hander for the TextChanged:
private void myTextBox_TextChanged(object sender, EventArgs e) {
TextBox box = sender as TextBox;
if (null == box)
return;
box.BackColor = box.Text.Trim().StartsWith("-")
? Color.Red
: Color.Green;
}
EDIT: The question in the comment is a quite different case; here we don't have events, but we can try extracting a method (NumSet):
private int m_Num1;
private int m_Num2;
private void NumSet(ref int num, int value) {
if (value == 1)
num = value + 1;
else
num = value - 1;
}
public int Num1 {
get => m_Num1;
set => NumSet(ref m_Num1, value);
}
public int Num2 {
get => m_Num2;
set => NumSet(ref m_Num2, value);
}
Related
The CurrentCellDirtyStateChanged event code will limit the number of checkboxes to (2). The rows with checked boxes contain editable data that is used to calculate values in the remaining unchecked readonly rows. I would like the datagrid to indicate editable rows by changing the color of the checked rows and have the remaining rows be readonly. The CurrentCellDirtyStateChanged event works for managing the checkboxes, but conflicts with the CellClick event for changing the row color. The boxes do not check and change color consistently. Any help would be greatly appreciated.
using System.Linq;
private void dgvParameters_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
if (dgvParameters.CurrentCell is DataGridViewCheckBoxCell && dgvParameters.IsCurrentCellDirty && !(bool)dgvParameters.CurrentCell.FormattedValue)
{
var count = dgvParameters.Rows.Cast<DataGridViewRow>()
.SelectMany(r => r.Cells.OfType<DataGridViewCheckBoxCell>()
.Where(c => (bool)c.FormattedValue))
.Count();
if (count == 2) dgvParameters.CancelEdit();
}
}
private void dgvParameters_CellClick(object sender, DataGridViewCellEventArgs e)
{
int index = dgvParameters.CurrentRow.Index;
DataGridViewCellStyle CheckedStyle;
DataGridViewCellStyle UnCheckedStyle;
CheckedStyle = new DataGridViewCellStyle();
UnCheckedStyle = new DataGridViewCellStyle();
CheckedStyle.BackColor = Color.White;
CheckedStyle.ForeColor = Color.Black;
UnCheckedStyle.BackColor = Color.LightGray;
UnCheckedStyle.ForeColor = Color.Black;
bool isSelect = dgvParameters[5, index].Value as bool? ?? false;
if (Convert.ToBoolean(row.Cells[5].Value))
{
dgvParameters.Rows[index].Cells[1].Style = CheckedStyle;
dgvParameters.Rows[index].Cells[3].Style = CheckedStyle;
dgvParameters.Rows[index].Cells[1].ReadOnly = false;
dgvParameters.Rows[index].Cells[3].ReadOnly = false;
}
else
{
dgvParameters.Rows[index].Cells[1].Style = UnCheckedStyle;
dgvParameters.Rows[index].Cells[3].Style = UnCheckedStyle;
dgvParameters.Rows[index].Cells[1].ReadOnly = true;
dgvParameters.Rows[index].Cells[3].ReadOnly = true;
}
}
You can continue with the CurrentCellDirtyStateChanged approach and handle the CellValueChanged event to set the properties of the same row's cells in question according to the new value of the DataGridViewCheckBoxCell.
First of all, make sure that you set the default values of the target cells either by the designer or code. I presume the initial value of the check box cells is false.
public YourForm()
{
InitializeComponent();
foreach (int i in new[] { 1, 3 })
{
dgvParameters.Columns[i].DefaultCellStyle.BackColor = Color.LightGray;
dgvParameters.Columns[i].DefaultCellStyle.ForeColor = Color.Gray;
dgvParameters.Columns[i].ReadOnly = true;
}
}
Secondly, modify the CurrentCellDirtyStateChanged event as follows...
private void dgvParameters_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
if (dgvParameters.CurrentCell is DataGridViewCheckBoxCell &&
dgvParameters.IsCurrentCellDirty)
{
if (!(bool)dgvParameters.CurrentCell.FormattedValue)
{
var count = dgvParameters.Rows.Cast<DataGridViewRow>()
.SelectMany(r => r.Cells.OfType<DataGridViewCheckBoxCell>()
.Where(c => (bool)c.FormattedValue))
.Count();
if (count == 2) dgvParameters.CancelEdit();
}
dgvParameters.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
}
Note the dgvParameters.CommitEdit(DataGridViewDataErrorContexts.Commit); line is there to apply and see the result as you toggle the value. Comment it if you need to keep the dirty state of the current row and commit the change on cell leave.
Lastly, handle the CellValueChanged event to update the target cells if the e.ColumnIndex is the index of the check box cell...
private void dgvParameters_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex >= 0 && e.ColumnIndex == 5)
{
var cell5 = dgvParameters.Rows[e.RowIndex].Cells[e.ColumnIndex];
bool isReadOnly = !(bool)cell5.FormattedValue;
Color backColor, foreColor;
if (isReadOnly)
{
backColor = Color.LightGray;
foreColor = Color.Gray;
}
else
{
backColor = Color.White;
foreColor = Color.Black;
}
foreach (int i in new[] { 1, 3 })
{
dgvParameters.Rows[e.RowIndex].Cells[i].Style.BackColor = backColor;
dgvParameters.Rows[e.RowIndex].Cells[i].Style.ForeColor = foreColor;
dgvParameters.Rows[e.RowIndex].Cells[i].ReadOnly = isReadOnly;
}
}
}
This way, you are just handling one row and you don't need to think about the rest.
Your question says that you would like a row that is not checked should to be ReadOnly. One obvious conflict is that if a row is truly read-only in its entireity, then there would be no way to ever check it to make it editable. My first suggestion would be to make a refreshStyles method that takes into account which cells are DataGridViewCheckBoxCell so that these can always be toggled regardless of the state of the row.
private void refreshStyles()
{
for (int i = 0; i < DataSource.Count; i++)
{
var item = DataSource[i];
var row = dataGridView.Rows[i];
// Use System.Linq to get all of the row cells that aren't checkboxes.
var cells =
row.Cells.Cast<DataGridViewCell>()
.Where(_ => !(_ is DataGridViewCheckBoxCell));
if(item.IsChecked)
{
row.DefaultCellStyle.BackColor = Color.Azure;
foreach (var cell in cells) cell.ReadOnly = false;
}
else
{
dataGridView.Rows[i].DefaultCellStyle.BackColor =
Color.FromArgb(0xf0, 0xf0, 0xf0);
foreach (var cell in cells) cell.ReadOnly = true;
}
}
}
This is a step towards having the DGV present with a mix of read-only and editable rows.
This is all based on having the DataSource property of the DGV set to a binding list of a class we'll call DgvItem that is minimally implemented as shown. The reason for making the IsChecked a binding property is in order to have the DataSource send a notification when its value changes (otherwise it only notifies when items are added or removed).
class DgvItem : INotifyPropertyChanged
{
bool _IsChecked = false;
public bool IsChecked
{
get => _IsChecked;
set
{
if (!Equals(_IsChecked, value))
{
_IsChecked = value;
OnPropertyChanged();
}
}
}
public string Description { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(
[CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Initialize
The only thing left is to glue it all together in the override of the Load event in MainForm.
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
dataGridView.AllowUserToAddRows = false;
// Set the DataSource of DGV to a binding list of 'DgvItem' instances.
dataGridView.DataSource = DataSource;
for (int i = 1; i <= 5; i++)
{
DataSource.Add(new DgvItem { Description = $"Item {i}" });
}
// Do a little column formatting
dataGridView.Columns[nameof(DgvItem.IsChecked)].Width = 50;
dataGridView.Columns[nameof(DgvItem.IsChecked)].HeaderText = string.Empty;
dataGridView.Columns[nameof(DgvItem.Description)].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
// Ensure the row isn't stuck in edit mode when a checkbox changes
dataGridView.CurrentCellDirtyStateChanged += (sender, e) =>
{
if(dataGridView.CurrentCell is DataGridViewCheckBoxCell)
{
dataGridView.EndEdit();
}
};
// Get notified when a checkbox changes
DataSource.ListChanged += (sender, e) =>
{
switch (e.ListChangedType)
{
case ListChangedType.ItemChanged:
// Make changes to row styles when that happens.
refreshStyles();
break;
}
};
// Init the styles
refreshStyles();
}
I hope this gives you a few ideas towards achieving the outcome you want.
Goal: The value I enter in the first box will be written in the second box
Goal: The second textbox will always write the highest value even if the first textbox changes
private void ModuleltextBox_TextChanged(object sender, EventArgs e)
{
try{
secondTxt.Text = firstTxt.Text;
var y = int.Parse(secondTxt.Text);
var x = int.Parse(firstTxt.Text);
if (y >= x)
{
//??
}
else if(x<y)
{
//??
}
}
catch (Exception){
}
You just need to set the Text property after comparing both text boxes value like :
try
{
var y = int.Parse(secondTxt.Text);
var x = int.Parse(firstTxt.Text);
if (y < x)
{
secondTxt.Text = x.ToString();
}
else
{
secondTxt.Text = y.ToString();
// or probably this line is not needed as y is already set in second TextBox
}
if first text box value is greater it will get set in secondTextBox otherwise the secondTextBox already have highest value.
I would think something like this would suffice?
private void ModuleltextBox_TextChanged(object sender, EventArgs e)
{
int x, y;
if (int.TryParse(firstTxt.Text, out x) && int.TryParse(secondTxt.Text, out y))
{
secondTxt.Text = Math.Max(x, y).ToString();
}
}
Put this piece of code in your textbox1 TextChanged event.
try
{
textBox2.Text = textBox1.Text;
int firstnum = int.Parse(textBox1.Text);
int secondnum = int.Parse(textBox2.Text);
}
catch
{
}
I think your second goal is not possible if you're using a TextChanged event since every changes you'll made in TextBox1 will be also made in TextBox2.
When a user writes some words in a rich text box, if that word matches some specific word, than the color of the that word should automatically change.
When the user clicks on that particular colored text, it should raise an event.
Given the requirements:
1) A User inserts some text in a RichTextBox Control.
2) If the word entered is part of a pre-defined list of words, that word should change color (so, define a relation between a word and a color).
3) When a mouse Click event is generated on a colored word, an event is raised, to notify which word was clicked.
Possible result (to replicate what's in the visual example):
Define a custom EventHandler with custom EventArgs:
public class WordsEventArgs : EventArgs
{
private string m_word;
public WordsEventArgs(string word) { m_word = word; }
public string Word { get { return m_word; } set { m_word = value; } }
}
public delegate void WordsEventHandler(object sender, WordsEventArgs e);
public event WordsEventHandler WordClicked;
protected void OnWordClicked(WordsEventArgs e) => WordClicked?.Invoke(this, e);
Subscribe to the event:
this.WordClicked += new WordsEventHandler(this.Word_Click);
Simple Class for the list of words:
public class ColoredWord
{
public string Word { get; set; }
public Color WordColor { get; set; }
}
public List<ColoredWord> ColoredWords = new List<ColoredWord>();
Fill the list with some words an related color, then bind it to a ListBox, calling the FillColoredWords() method (in other words, handle a collection of objects that relate pieces of text with Color values):
public void FillColoredWords()
{
ColoredWords.Add(new ColoredWord { Word = "SIMPLE", WordColor = Color.Goldenrod });
ColoredWords.Add(new ColoredWord { Word = "COLORED", WordColor = Color.Salmon });
ColoredWords.Add(new ColoredWord { Word = "TEXT", WordColor = Color.DarkCyan });
this.listBox1.DisplayMember = "Word";
this.listBox1.DataSource = ColoredWords;
}
In the KeyPress event, evaluate whether the last entered word is part of the list of words to color:
private void richTextBox1_KeyPress(object sender, KeyPressEventArgs e)
{
int currentPosition = richTextBox1.SelectionStart;
if (e.KeyChar == (char)Keys.Space && currentPosition > 0 && richTextBox1.Text.Length > 1) {
int lastSpacePos = richTextBox1.Text.LastIndexOf((char)Keys.Space, currentPosition - 1);
lastSpacePos = lastSpacePos > -1 ? lastSpacePos + 1 : 0;
string lastWord = richTextBox1.Text.Substring(lastSpacePos, currentPosition - (lastSpacePos));
ColoredWord result = ColoredWords.FirstOrDefault(s => s.Word == lastWord.ToUpper());
richTextBox1.Select(lastSpacePos, currentPosition - lastSpacePos);
if (result != null) {
if (richTextBox1.SelectionColor != result.WordColor) {
richTextBox1.SelectionColor = result.WordColor;
}
}
else {
if (richTextBox1.SelectionColor != richTextBox1.ForeColor) {
richTextBox1.SelectionColor = richTextBox1.ForeColor;
}
}
richTextBox1.SelectionStart = currentPosition;
richTextBox1.SelectionLength = 0;
richTextBox1.SelectionColor = richTextBox1.ForeColor;
}
}
In the MouseClick event, verify whether the event is generated on a colored word.
In that case, raise the custom OnWordClicked() event:
private void richTextBox1_MouseClick(object sender, MouseEventArgs e)
{
if (richTextBox1.SelectionColor.ToArgb() != richTextBox1.ForeColor.ToArgb()) {
try {
int wordInit = richTextBox1.Text.LastIndexOf((char)32, richTextBox1.SelectionStart);
wordInit = wordInit > -1 ? wordInit : 0;
int wordEnd = richTextBox1.Text.IndexOf((char)32, richTextBox1.SelectionStart);
string wordClicked = richTextBox1.Text.Substring(wordInit, wordEnd - wordInit) + Environment.NewLine;
OnWordClicked(new WordsEventArgs(wordClicked));
}
catch (Exception) {
//Handle a fast DoubleClick: RTB is a bit dumb.
//Handle a word auto-selection that changes the `.SelectionStart` value
}
}
}
In the custom event, you can append the clicked word to a TextBox (or do whatever else you want to do with it):
private void Word_Click(object sender, WordsEventArgs e)
{
textBox1.AppendText(e.Word);
}
first of all add an event to your rich box text changed,then
you need to change the color of text if that is an specific word like for example : Munis , Ali
private void Rchtxt_TextChanged(object sender, EventArgs e)
{
this.CheckKeyword("Munis", Color.Purple, 0);
this.CheckKeyword("Ali", Color.Green, 0);
}
I use objectlistview (2.9.1), I want to rollback the value of CellEditor.Text when the input is not qualified, and display on UI immediately.
Code:
private void olv_CellEditFinishing(object sender, CellEditEventArgs e)
{
int iQuantity = 0;
int iPreviousQuantity = order.Quantity.HasValue ? order.Quantity.Value : 0;
string sCellText = ((ObjectListView)sender).CellEditor.Text;
if (Int32.TryParse(sCellText, out iQuantity) && iQuantity >100)
{
// pop up a message box
//Here I want to rollback the previouse quantity
((ObjectListView) sender).CellEditor.Text = iPreviousQuantity.ToString();
//display the previous quantity immedidatly
this.olv.RefreshItem(e.ListViewItem);
}
}
but this does not work.
Make sure you register the event :
this.DBTLviewAfter.CellEditFinishing += new BrightIdeasSoftware.CellEditEventHandler(this.DBTLviewAfter_CellEditFinishing);
and here is my event function:
private void DBTLviewAfter_CellEditFinishing(object sender, CellEditEventArgs e)
{
string toBeEditingStr = (string)e.NewValue;
if(toBeEditingStr == "")
{
e.Cancel = true;
}
}
If the value after edited is empty, the cell won't be changed.
This is the weirdest thing as it works for me in some code in not other. The following code is in a class that subclasses TextBox (NOTE: I don't know if it matters but I subclass the Text property to set/get from a private field _realText)
In the below code, the first base.Text = this.RealText works fine!!! We also set it inside that method MaskData() as well and it works!!!! so why in the world does it not work in the if(!field.isSecure) section? (look at the logs for what I mean). I tried adding Invalidate(), Update() after base.Text=temp but that didn't help.
Code:
private void SetupTextInBox()
{
if (isInManualMode)
{
this.ReadOnly = false;
base.Text = this.RealText;
}
else
{
this.ReadOnly = true;
if (!field.IsSecure)
{
string temp = this.RealText;
log.Info("This field is not secure so show it. field=" + field.Variable + " real='" + temp+"'");
base.Text = temp;
log.Info("text value='" + base.Text+"'");
return;
}
else
{
MaskData();
}
}
}
Logs
2012-06-30 07:15:51,468 [1] INFO AlpineAccess.Plugins.SecureTalkPlugin.SecureTextControl (null) - This field is not secure so show it. field=1.acc real='2222'
2012-06-30 07:15:51,468 [1] INFO AlpineAccess.Plugins.SecureTalkPlugin.SecureTextControl (null) - text value=''
EDIT: Note that this method is ALWAYS called from the same thread. It comes from server notifications telling us a tone on a phone somewhere else has been pressed, AND then that thread calls a BeginInvoke to put it in the GUI/controls thread or whatnot.
code just upstream from the above method is
public void AppendDTMFDigit(string digit)
{
log.Info("specified="+field.MaxSpecified+" someone appending dtmf digit on field=" + field.Variable+" fieldMax="+field.Max+" len="+RealText.Length);
if (field.MaxSpecified && this.RealText.Length >= field.Max)
return; //shortcut out since we can't exceed max digits
BeginInvoke(new MethodInvoker(delegate()
{
this.RealText = this.RealText + digit;
log.Info("new realtext=" + this.RealText);
SetupTextInBox();
}
));
}
MORE INFO: If I change ALL my client code to stop using Text property and use RealText property, and then stop overriding the Text property, it then works fine. (Obviously I don't want that though as now I can't just change from my control to TextBox and back easily without changing lots of client code referring to the RealText property....ugh, may have to live with that though....seems like some kind of odd bug.
MORE INFO: got debugger stepping into it and this is very odd.
2 very odd things.
It steps into the getter, not the setter???
It steps into MY Text property instead of TextBox's Text Property.
grrrrr, why would that be...sounds like a major bug, right? I mean, base.Text should refer to superclass's base, correct? – Dean Hiller just now edit
Adding Text method property code
public override string Text
{
get
{
return RealText;
}
set
{
if (value == null)
throw new ArgumentException("Not allowed to set RealText to null. Set to empty string instead");
RealText = value;
}
}
Full source for this user control that doesn't work unless you comment out the Text property is here (You would have to use a RealText property and expose that one to clients instead because base.Text does not appear to work properly).
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using log4net;
using IntraNext.Win32.Config;
namespace AlpineAccess.Plugins.SecureTalkPlugin
{
public partial class SecureTextBox : TextBox
{
private static readonly ILog log = LogManager.GetLogger(typeof(SecureTextControl));
private static readonly Color COLOR_FOCUSED = Color.Yellow;
private static readonly Color COLOR_FOCUSED_MANUALMODE = Color.PaleGreen;
private FocusEvent focusListener;
private Field field;
private bool isInManualMode;
private EventHandler textChanged;
private string RealText;
public SecureTextBox()
{
InitializeComponent();
RealText = "";
}
internal void Initialize(Field field, FocusEvent focusList, EventHandler textChanged)
{
this.focusListener = focusList;
this.textChanged = textChanged;
this.field = field;
this.Enter += new EventHandler(SecureTextBox_Enter);
this.Leave += new EventHandler(SecureTextBox_Leave);
this.TextChanged += new EventHandler(SecureTextBox_TextChanged);
MenuItem mnuItemNew = new MenuItem();
mnuItemNew.Text = "&Clear";
//THIS textbox HAS a context menu ALREADY BUT here we assign a new context menu to
//our text box to replace the old one which had cut, paste etc. that we don't want
//the agent using...
this.ContextMenu = new ContextMenu();
this.ContextMenu.MenuItems.Add(mnuItemNew);
mnuItemNew.Click += new EventHandler(clear_Click);
SwitchModes();
}
void SecureTextBox_TextChanged(object sender, EventArgs e)
{
if(isInManualMode) //make sure if in manual mode, we keep changes up to date in realText field
RealText = Text;
textChanged(sender, e);
}
void clear_Click(object sender, EventArgs e)
{
ClearAll();
}
internal void SetManualMode(bool inManual)
{
if (isInManualMode == inManual)
return; //we don't care if there is no change so return;
isInManualMode = inManual;
SwitchModes();
}
void SecureTextBox_Leave(object sender, EventArgs e)
{
log.Info("exiting=" + field.Variable);
focusListener(field.Variable, false, this.RealText);
BeginInvoke(new MethodInvoker(delegate()
{
ChangeBackground();
}
));
}
void SecureTextBox_Enter(object sender, EventArgs e)
{
log.Info("entering=" + field.Variable );
focusListener(field.Variable, true, this.RealText);
BeginInvoke(new MethodInvoker(delegate()
{
ChangeBackground();
}
));
}
private void SwitchModes()
{
SetupTextInBox();
ChangeBackground();
}
private void SetupTextInBox()
{
if (isInManualMode)
{
this.ReadOnly = false;
base.Text = RealText;
}
else if (!field.IsSecure)
{
this.ReadOnly = true;
string temp = RealText;
base.Text = temp;
Invalidate();
log.Info("txt=" + base.Text + " temp=" + temp);
}
else //not manual mode and IsSecure so mask it and make it readonly
{
this.ReadOnly = true;
MaskData();
}
}
private void MaskData()
{
log.Debug("mask=" + this.field.NumBeginDigitsToMaskSpecified + " num=" + field.NumBeginDigitsToMask + " txtLen=" + RealText.Length);
int numDigitsToMask = RealText.Length;
if (this.field.NumBeginDigitsToMaskSpecified && this.field.NumBeginDigitsToMask < RealText.Length)
{
int numDigits = this.field.NumBeginDigitsToMask;
string maskedPart = "".PadLeft(numDigits, '●');
string unmasked = RealText.Substring(numDigits);
string full = maskedPart + unmasked;
base.Text = full;
}
else
{
log.Debug("masking all digits");
base.Text = "".PadLeft(RealText.Length, '●');
}
}
private void ChangeBackground()
{
if (isInManualMode)
SetManualModeColor();
else
SetNonManualModeColor();
}
private void SetNonManualModeColor()
{
if (this.Focused)
this.BackColor = COLOR_FOCUSED;
else
this.BackColor = Control.DefaultBackColor;
}
private void SetManualModeColor()
{
if (this.Focused)
this.BackColor = COLOR_FOCUSED_MANUALMODE;
else
this.BackColor = Control.DefaultBackColor;
}
public void AppendDTMFDigit(string digit)
{
log.Info("manualmode="+isInManualMode+" specified=" + field.MaxSpecified + " someone appending dtmf digit on field=" + field.Variable + " fieldMax=" + field.Max + " len=" + RealText.Length);
if (isInManualMode)
return;
else if (field.MaxSpecified && RealText.Length >= field.Max)
return; //shortcut out since we can't exceed max digits
BeginInvoke(new MethodInvoker(delegate()
{
RealText = RealText + digit;
SetupTextInBox();
}
));
}
internal void ClearAll()
{
log.Info("Cleared textbox for =" + field.Variable);
base.Text = "";
RealText = "";
SetError("");
}
public override string Text
{
get
{
return RealText;
}
set
{
if (value == null)
throw new ArgumentException("Not allowed to set RealText to null. Set to empty string instead");
RealText = value;
}
}
/**
* Set to "" to clear the error or set anything to make valid
*/
public void SetError(string error)
{
if (!this.IsHandleCreated)
return;
SecureTextBox box = this;
//set to "" to clear the error
BeginInvoke(new MethodInvoker(delegate()
{
errorProvider1.SetError(box, error);
}));
}
}
}
Ok you've overridden Text - and you have THIS on one of your lines:
RealText = Text;
This will call the most derived 'Text' property (since you didn't specify base) and will call your overridden 'Text' on the current control
Which means you are setting RealText to itself
e.g.
void SecureTextBox_TextChanged(object sender, EventArgs e)
{
if (isInManualMode) //make sure if in manual mode, we keep changes up to date in realText field
RealText = Text; <---- **THIS CALLS THE OVERIDDEN 'Text' BELOW**
... snip
calls
public override string Text
{
get { return RealText; }
}
Which is a bit...nuts!
Did you mean to do:
void SecureTextBox_TextChanged(object sender, EventArgs e)
{
if (isInManualMode) //make sure if in manual mode, we keep changes up to date in realText field
RealText = base.Text; <--- THIS?
Check your code carefully, I bet this is one of your issues
Also it might be useful to change your naming conventions a little... e.g. I tend to use an underscore for private/protected fields
private string _realText;
instead of caps which is for properties
private string RealText;
Don't usually expose public fields, usually use properties but when I do I tend to use the same casing as I do for properties
This is so that it's easier to differentiate between properties and fields in your code and makes debugging a bit easier