Making TextBox Clear when user starts typing - c#

I have two text boxes in a win forms that the user will be typing information into. I would like to clear the text box when the user start typing. I am using the TextChanged event handler, so every time I type it will erase, which makes me not able to type anything into the text box. Here is the code I am using:
private void TXTBX_HourlyRatae_TextChanged(object sender, EventArgs e)
{
TXTBX.HourlyRate.Clear();
TXTBX.HoursWorked.Clear();
}
I understand that everytime I type into the text box I will be executing this event handler, but I don't know how to go about making it execute only the first time I type into the text box.

private bool firsttime = true;
private void TXTBX_HourlyRatae_TextChanged(object sender, EventArgs e)
{
if (firsttime)
{
TXTBX.HourlyRate.Clear();
TXTBX.HoursWorked.Clear();
firsttime = false;
}
}
if you want to do it everytime you enter the textbox handle the loss focus event
private void TXTBX_HourlyRatae_LostFocus(object sender, System.EventArgs e)
{
} firsttime = true;

Move your Clear() calls into the corresponding Enter or GotFocus events.

Create a new private class member:
private bool _userHasEnteredText = false;
Only erase the text when this bool is false, then set this bool to true once you've cleared the text the first time.

Related

Remove Entry Text at first click

I have a entry/Textbox. And i have 10 number buttons as a calculator.(0-1-2-3-4....) When my page loaded entry having a number. Its showing me start value.( For example when my page loaded entry text being 10 already without any click to button) So i want to when i click a number button It will delete first entry value that loaded with page and it will start write my button clicks. How can I do it ?
I tried with:
private void btn1_Clicked(object sender, EventArgs e)
entry.Text="";
entry.Text="1";
But of course it didn't work because if i want to write 123 I cant write its always deleting. I just want delete first value which is coming with page loaded.
As #Jason suggested use the Placeholder property to display the initial value and in the click events append the value to the entry text:
Note: you can have a single event delegate that handle the click event for all buttons:
Constructor()
{
//set initial value here or use binding
//entry.Placeholder =
}
private void btn_Clicked(object sender, EventArgs e)
{
//you can remove the initial value if you want
//entry.Placeholder = string.Empty;
string buttonText = ((Button)sender).Text;
entry.Text = $"{entry.Text}{buttonText}";
}
An alternative way is to add a boolean flag out of the method to avoid this.
public class MyCalculator ()
{
private bool _isNewNumber;
protected override void OnAppearing()
{
_isNewNumber = true; //whenever open the page, needs to refresh
}
private void btn1_Clicked(object sender, EventArgs e)
{
if (_isNewNumber)
{
entry.Text=""; //clear the number for the first time
}
entry.Text="1";
_isNewNumber = false;
}
}

Make text box only highlight text on first click only

Currently I have it so that when you select the text box it will highlight the text in it but what I want it to do is only do this for the first time that it is selected so that it will not delete the text that the user is typing each time. Here is what I am using to highlight the text:
private void txtName_Focus(object sender, EventArgs e)
{
bool isFirstTime = true;
if (isFirstTime == true){
txtName.SelectionStart = 0;
txtName.SelectionLength = txtName.Text.Length;
}
isFirstTime = false;
}
bool isFirstTime = true; this is your problem. It is being initialized to true every time the focus event is being called. Move bool isFirstTime; to be a member of your class and initialize it to true once in the declaration, constructor or the form load event
Maybe something like this:
bool txtNameWasFocused=false;
private void txtName_Focus(object sender, EventArgs e)
{
if(!txtNameWasFocused){
txtNameWasFocused=true;
txtName.SelectionStart = 0;
txtName.SelectionLength = txtName.Text.Length;
}
}
If you need this in many places, you might think of a derived text box with this special behaviour...

TextChanged event firing as soon as I open the app

So I am making an app in C# where it creates/edits existing .ini files. One of the features I am trying to add is that if I make changes to the .ini file via the c# app I created, and either try to close the app, open another .ini file or create a new file, it should prompt the user if they want to save the file. To accomplish this, I have a flag called dataChanged. In the TextChanged events in for the multiple textboxes, I set dataChanged = true; since changes were made to the file. However, for some reason as soon as I open the app, all the TextChange events fire up so even if I don't enter any values in the various textboxes, when I close the app, it prompts me to save the file (it shouldn't!).
App UI:
User inputs text in the textboxes.
Part of code regarding the 4 textboxes:
private void TextBox_TextChanged(object sender, TextChangedEventArgs e) //ifrs installer
{
dataChanged = true;
}
private void TextBox_TextChanged_1(object sender, TextChangedEventArgs e) //ifrs patchfile
{
dataChanged = true;
}
private void textBox3_TextChanged(object sender, TextChangedEventArgs e)
{
dataChanged = true;
}
private void textBox4_TextChanged(object sender, TextChangedEventArgs e)
{
dataChanged = true;
}
TextChanged event fires even when you set some Text. Apparently you set some initial text when app is loading.
You can subscribe to the event mannually after you set the initial value.
textBox4.TextChanged += textBox4_TextChanged;
or unsubscribe before you set the value and subscribe after that.
textBox4.TextChanged -= textBox4_TextChanged;
textBox4.Text = "Initial Value";
textBox4.TextChanged += textBox4_TextChanged;
Sounds to me like you're programmatically setting the textBoxN.Text properties.
What you might want to do is add an if (appInitialized) around your dataChanged = true; and only set appInitialized to true after the application is loaded, perhaps in your Form_Load event. This way, the initial loading doesn't set your variable. Another option is to only register the TextChanged event after you have already set the initial values. My guess is you registered the event using the designer and as a result it's firing for those initial settings because of where the designer adds event registration. Instead do the
textBox4.TextChanged += textBox4_TextChanged;
// Etc. for each text box
yourself after the .Text properties are set. Again, perhaps in your Form_Load.
I'm guessing you are loading the ini file when the program loads and this triggers to text changed event. I suggest doing something like this.
private void Form1_Load(object sender, EventArgs e)
{
LoadData();
}
private bool _LoadingData = false;
private bool _DataChanged = false;
private void LoadData()
{
try
{
_LoadingData = true;
// Load data
}
finally
{
_LoadingData = false;
}
}
public void DataChanged()
{
if (_LoadingData == false)
{
_DataChanged = true;
}
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
DataChanged();
}

2 events calling each other

I was wondering about this problem for a while, but couldn't really come up with a solution. I have 2 different event handlers calling each other recursively. As soon as event A is fired, it triggers event B which triggers event A again and so on...
Basically I want to be able to select text in a RichTextBox and show the corresponding font size in a combo box. When I choose a different font size from the ComboBox, I want it's value to be applied to the selected text.
The 2 events are:
1) The selection changed event of text inside a RichTextBox:
private void MyRTB_SelectionChanged(object sender, RoutedEventArgs e)
{
//Get the font size of selected text and select the concurrent size from the ComboBox.
}
2) The selected index changed event of a Combobox:
private void CmbFont_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
//Apply the chosen font size to the currently selected text of the RichTextBox.
}
What would be the best solution to make sure they each only "do their thing" and do not fire the other event in doing so?
Sometimes changing a property of a control in code fires an event unintentionally. Changing the data source of a ListBox or a ComboBox will fire the SelectedIndexChanged event, for example. Use a flag to handle this case
private bool _loading;
...
_loading = true;
// Fill the ComboBox or ListView here
_loading = false;
In the event handler do this
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (_loading) return;
...
}
Refactor your code so that A calls DoSomethingA() and B calls DoSomethingB(). This way, if you want A to do the functionality of B you can just call DoSomethingB() and not have any recursive calls.
Just use a bool (maybe called dontFireA) and set it in A just before calling B
notifying properties (used in order to enable binding from WPF to non-WPF properies) use this technique:
public object MyProperty
{
get
{
return myField;
}
set
{
if (value != myField)
{
myField = value;
NotifyProperyChanged("MyProperty"); // raise event
}
}
}
The if (value != myField) condition prevents infinite recursion (stackoverflowexception).
In some cases (e.g. floating point numbers and inaccurate value transfers) if (Math.Abs(value - myField) > someConstant) is used instead to break the recursion.
Could you apply a similar technique to your problem?
If both events are on the same object or the owners have references to each other, you could also store a flag on each e.g.
private void OnEvent()
{
DoSomething();
}
private void DoSomething()
{
this.IsBusy = true;
// do work
// raise event
if (!other.IsBusy)
RaiseEvent();
}
I am going to make the educated guess that you are not raising Event A or Event B yourself; let's say Event A is the TextBox1.TextChanged event and Event B is the TextBox2.TextChanged event, and they have handlers like:
public void Textbox1_TextChanged(object sender, EventArgs e)
{
...
TextBox2.Text = someString;
}
public void Textbox2_TextChanged(object sender, EventArgs e)
{
...
TextBox1.Text = someOtherString;
}
In this case, the handlers are each going to raise the other textbox's TextChanged event by virtue of changing the text, leading to infinite recursion.
The first thing you can do, if you want both to run once and once only, is to mark that they're already running (changing the text of the other textbox results in that textbox's event handler running within the same call stack:
public void Textbox1_TextChanged(object sender, EventArgs e)
{
if(handler1Running) return; //the second time through we exit immediately
handler1Running = true;
...
TextBox2.Text = "Something"; //the other event handler is invoked immediately
handler1Running = false;
}
public void Textbox2_TextChanged(object sender, EventArgs e)
{
if(handler2Running) return; //the second time through we exit immediately
handler2Running = true;
...
TextBox1.Text = "Something Else"; //the other event handler is invoked immediately
handler2Running = false;
}
Now, the deepest it will go is three levels; 1's handler invokes 2's handler which invokes 1's handler again, which sees that 1's handler is already running and quits before doing anything that would deepen the recursion. Same thing if you start by changing TextBox2.
The other thing you can do is make sure you aren't trying to set the textbox to the same value that's already there. Changing from one string reference to another, even if both references are the same string value, will fire the TextChanged event. If the recursion must continue naturally but will reach a steady state, this is actually the first thing to try:
public void Textbox1_TextChanged(object sender, EventArgs e)
{
StringBuilder builder = new StringBuilder();
... //build string
//now, even though the builder's ToString will produce a different reference,
//we're making sure we don't unnecessarily change the text.
if(builder.ToString != TextBox2.Text)
TextBox2.Text = builder.ToString();
}
public void Textbox2_TextChanged(object sender, EventArgs e)
{
StringBuilder builder = new StringBuilder();
... //build string
//now, even though the builder's ToString will produce a different reference,
//we're making sure we don't unnecessarily change the text.
if(builder.ToString != TextBox1.Text)
TextBox1.Text = builder.ToString();
}

Why is there an infinite loop on my LostFocus Event

I'm a beginner with C# and I'm developing a basic application.
I want to check if the value of a textbox is a number with the following code :
private void check_value(object sender)
{
TextBox tb = (TextBox)sender ;
if (!Utility.isNumeric(tb.Text)){
MessageBox.Show(tb.Text.Length.ToString());
tb.Focus();
}
}
private void Amount_1_LostFocus(object sender, RoutedEventArgs e)
{
check_value(sender);
}
When I enter a letter in the textbox there is an infinite loop and it seems that the tb.Focus() actually cause the LostFocus event to be call recursively.
I don't understand why the call to the Focus method of an object triggers the LostFocus event of the same object.
Opening the modal MessageBox is responsible for loosing the focus. Try hook to Validating event.
As i said before in the link provided by Xaqron it's said that it's forbidden to use the Focus method in the LostFocus event.
And as I'm developing a WPF application there is no Validating event and CausesValidation property, so the others ways to validate the content is to use the TextChanged event or use binding validation.
Thank you for your answers.
Of course, in a perfectly valid program, you should not change Focus in the LostFocus event. This also applies to the Enter, GotFocus, Leave, Validating and Validated events, which Ms makes clear in the documentation https://learn.microsoft.com/pl-pl/dotnet/api/system.windows.forms.control.lostfocus.
However, in very unusual cases, you can use the timer to trigger changes to the Focus, bypassing this problem.
private TextBox tb = null;
private System.Windows.Forms.Timer MyTimer;
private void initialize()
{
MyTimer.Tick += new System.EventHandler(MyTimer_Tick);
MyTimer.Enable = false;
MyTimer.Interval = 100;
}
private void check_value(object sender)
{
tb = (TextBox)sender ;
if (!Utility.isNumeric(tb.Text)){
MessageBox.Show(tb.Text.Length.ToString());
MyTimer.Enable = true;
}
}
private void Amount_1_LostFocus(object sender, RoutedEventArgs e)
{
check_value(sender);
}
private void MyTimer_Tick(object sender, EventArgs e)
{
MyTimer.Enabled = false;
if (tb!=null) tb.Focus();
}

Categories

Resources