I can highlight the text in an individual MaskedTextBox when it gets focus using:
this.myTextBox.SelectAll();
But, I want to do it for all MaskedTextBox when a mouse click event occurs. Instead of adding 30 individual event method for each MaskedTextbox, I want to select all MaskedTextBox and have one event method to take care of it, ie:
private void MouseClickedForMaskedTextBox(object sender, MouseEventArgs e)
{
this.ActiveControl.SelectAll();
}
But SelectAll is not available for this.ActiveControl. Is there a way to get around it?
sender will be the target of the event.
You could cast sender:
MaskedTextBox maskedTextBox = sender as MaskedTextBox;
if (maskedTextBox != null) { maskedTextBox.SelectAll(); }
Or in C# 7,
if (sender is MaskedTextBox maskedTextBox)
{
maskedTextBox.SelectAll();
}
Another improvement is to use TextBoxBase and it will work with TextBox and RichTextBox as well.
Put the following code in the form's constructor:
foreach (Control c in Controls)
{
if (c is TextBox)
{
TextBox tb = c as TextBox;
tb.GotFocus += delegate { tb.SelectAll(); };
}
}
Simply do that:
private void maskedTextBox1_Enter(object sender, EventArgs e)
{
this.BeginInvoke((MethodInvoker) delegate() {
maskedTextBox1.SelectAll();
});
}
I found another way by creating or edit your User Control that inherits MaskedTextBox. In the designer you set true the property "OnEnterSelectAll".
public partial class MaskedTextBoxX : MaskedTextBox
{
public MaskedTextBoxX()
{
InitializeComponent();
Inicializar();
}
// ===============================
// Campos AƱadidos
// ===============================
public bool OnEnterSelectAll { get; set; } = false;
// ===============================
// Metodos
// ===============================
private void Inicializar()
{
// *** SELECCIONAR TODO el MarkedTextBox
Click += delegate { if (OnEnterSelectAll) SelectAll(); };
}
}
Related
I have a custom WPF TextBox User Control. Im writing some content, but it always detects the same data that was preset on the XAML, new written text is not shown by doing textbox.Text get call.
public partial class SearchBox : UserControl
{
public SearchBox()
{
InitializeComponent();
this.DataContext = this;
}
private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
if (sender is TextBox textBox && textBox.Tag.ToString() == textBox.Text)
textBox.Clear();
}
private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
if (sender is TextBox textBox && string.IsNullOrEmpty(textBox.Text))
textBox.Text = textBox.Tag.ToString();
}
public string Text { get; set; }
public event TextChangedEventHandler TextChanged;
private void TextBox_TextChanged(object sender, TextChangedEventArgs args)
{
TextChangedEventHandler h = TextChanged;
if (h != null)
{
h(this, args);
}
}
}
How it needs to work:
<v:SearchBox x:Name="searchBox" TextChanged="searchBox_TextChanged" Text="Input a keyword to filter..." Tag="Input a keyword to filter..." HorizontalAlignment="Left"/>
User writes on textbox "test" --> textbox.Text returns "Input a keyword to filter..."
Thanks for the help!
Your class inherits from UserControl and not TextBox.
Though you haven't shared your XAML for SearchBox, I assume you have a TextBox in it, which you are hoping to get the text from. Problem is, the property SearchBox.Text is different from SearchBox.TextBox.Text. As a result, even if you change the text in the TextBox, SearchBox.Text remains the same.
Solution: use SearchBox.TextBox.Text for your result.
I have a class that creates a Label and display text.
I also have a Click event that when it fires, the Label text changes.
I have another class, that passes a method to the first one that shows a MessageBox.
In the main Form I'm running a for loop that creates 2 instances of the class at random locations.
The problem is, when I click a Label, the text doesn't change on the Label that I want. It changes to the first Label (class) created.
How can I change that?
class J1
{
public Label texto;
public static int a = 0;
//Calls the Method that Creates the Label
public void Spawn(Form form, int _X, int _Y)
{
LL(form, _X, _Y);
}
//Creates the label
public void LL(Form form, int _X, int _Y)
{
texto = new Label()
{
Size = new System.Drawing.Size(35, 50),
Left = _X,
Top = _Y,
Text = "nova label"
};
texto.Click += new EventHandler(Label_Clicada);
form.Controls.Add(texto);
}
void Label_Clicada(object sender, EventArgs e) //Click event when fires
{
J2.M(); //2nd Class that shows a MessageBox
//Changes Text, but doenst change the one that was clicked on
texto.Text = texto.GetType().ToString();
}
}
2nd Class(J2):
class J2
{
public static void M()//Method that I pass to 1nd class(J1)
{
J1.a++;
MessageBox.Show(J1.a.ToString());
}
}
As i posted in comment solution for this was using (sender as Label).Text in click event.
sender is type of object which contains object which fired event.
If we take a look at how events are fired with this code:
EventHandler<ThresholdReachedEventArgs> handler = ThresholdReached;
if (handler != null)
{
handler(this, e);
}
We can see that hanlder(this, e); is passing this object which fires it and e as some parameters (event args).
Now this / object that passed event could be any object if you bind multiple objects to same event.
For example if you do yourButton.Click += ClickEvent; and yourLabel.Click += ClickEvent both buttons inside have code above but both of them will pass different this (themselves) and e (events if there are any)
so inside our event we can do this:
private void ClickEvent(object sender, EventArgs e)
{
if(sender is Label)
{
Label l = sender as Label;
//Do anything with label
}
else if(sender is Button)
{
Button b = sender as Button;
//Do anything with button
}
else
{
MessageBox.Show("Unknown component");
//Or
throw new Exception("Unknown component");
}
}
I extended the button control to have also LabelName. When I press the button I need to write the name of the button in the label.
My first idea was using events - easy and simple.
The question is: Is there more elegant way to do it? (I've been asked to bind the button and the label)...
I think that the best way to do it would be to use an action listener and the best way to use the action listener would be to build it into your class that extends the button control so that the user doesn't have to do this on their own. It would look like this.
class Button2 : Button
{
public string LabelName = "";
public Button2()
{
this.Click += this.SetLabelName;
}
private void SetLabelName(object sender, EventArgs e)
{
this.LabelName = "Something?";
}
//You could also do this instead.
protected override void OnClick(EventArgs e)
{
base.OnClick(e);
}
}
If you're talking about changing the Text property of an external Label control, then simply create a property in your Button to hold a reference to a Label. You can set this via the IDE like any other property:
Here's the Button class:
public class MyButton : Button
{
private Label _Label = null;
public Label Label
{
get { return _Label; }
set { _Label = value; }
}
protected override void OnClick(EventArgs e)
{
base.OnClick(e);
if (this.Label != null)
{
this.Label.Text = this.Name;
}
}
}
Here's the Label after I clicked the Button:
I have a TextChanged event on my ComboBox like;
private void comboBox1_TextChanged(object sender, EventArgs e)
{
foreach (var item in comboBox1.Items.Cast<string>().ToList())
{
comboBox1.Items.Remove(item);
}
foreach (string item in InputBox.AutoCompleteCustomSource.Cast<string>().Where(s => s.Contains(comboBox1.Text)).ToList())
{
comboBox1.Items.Add(item);
}
}
As an explanation, when I change the text of combobox, I want to get string values contains in AutoCompleteCustomSource on InputBox (which is TextBox).
It works fine when I search them but when I select the item, obviously TextChanged event triggered again and Text property of Combobox will reset.
How to solve this?
If I understood correctly then i think you want to hide the TextChange event of the combobox. If it is then you can create a custom control inherited by ComboBox and override the TextChange event.
public partial class MyCombo : ComboBox
{
public MyCombo()
{
InitializeComponent();
}
bool bFalse = false;
protected override void OnTextChanged(EventArgs e)
{
//Here you can handle the TextChange event if want to suppress it
//just place the base.OnTextChanged(e); line inside the condition
if (!bFalse)
base.OnTextChanged(e);
}
protected override void OnSelectionChangeCommitted(EventArgs e)
{
bFalse = true;
base.OnSelectionChangeCommitted(e);
}
protected override void OnTextUpdate(EventArgs e)
{
base.OnTextUpdate(e);
bFalse = false; //this event will be fire when user types anything. but, not when user selects item from the list.
}
}
EDITED:
Another simple soution is use TextUpdate event instead of TextChange and keep your combobox as it is without creating another custom control.
private void myCombo1_TextUpdate(object sender, EventArgs e)
{
foreach (var item in myCombo1.Items.Cast<string>().ToList())
{
myCombo1.Items.Remove(item);
}
foreach (string item in myCombo1.AutoCompleteCustomSource.Cast<string>().Where(s => s.Contains(myCombo1.Text)).ToList())
{
myCombo1.Items.Add(item);
}
}
TextUpdate event will call only when user types anything in combobox. But, not when user selects item from the drop down list. So, this will not resent the added items.
You can also change the where condition if you wish to return all matched items in both cases(Upper and Lower). Suppose you have a two items in the list 1. Microsoft Sql Server, 2. microsoft office then what would be the result if i type microsoft only.
Where(s => s.ToLower().Contains(comboBox1.Text.ToLower()))
Sample Code
As #Sayse already said:
Add a boolean:
private bool codeCalled = new bool();
In your textChanged:
if(codeCalled == true)
{
codeCalled = false;
return;
}
else
{
codeCalled = true;
//your foreachcode here
}
That should do the trick.
Tested and is working.
Also tested and working, also not elegant:
private void textBox_TextChanged(object sender, EventArgs e)
{
textBox.TextChanged -= textBox_TextChanged;
//yourcode
textBox.TextChanged += textBox_TextChanged;
}
im doing an application where user enter a value inside the text box then he press a button, both in the same user control. Then the result from the text box will show at the label of other user control. Both of the user control is in the same windows form.
Thanks!
Image of user interface
The most common way to do this is use an event. This is how I would do it:
First define an EventArgs:
public class MyEventArgs : EventArgs
{
public string Text { get; private set; }
public MyEventArgs(string Text)
{
this.Text = Text;
}
}
Then in your UserControl (the one with the button):
public partial class MyUserControl
{
public event EventHandler<MyEventArgs> ButtonClicked;
public MyUserControl()
{
//...
button1.Click += (o, e) => OnButtonClicked(new MyEventArgs(textBox1.Text));
}
protected virtual void OnButtonClicked(MyEventArgs args)
{
var hand = ButtonClicked;
if(hand != null) ButtonClicked(this, args);
}
}
Then subscribe to your MyUserControl.ButtonClicked event in the form and call a method in the second control.
Note if the behavior of the button and the text in the textbox are actually not related, you can use a property to get the text entered and an empty EventArgs for your event instead.
P.S. The names MyEventArgs, MyUserControl, and ButtonClicked are just for demonstration purposes. I encourage you to use more descriptive/relevant naming in your code.
try this:
public class FirstUserControl:UserControl
{
Public event EventHandler MyEvent;
//Public property in your first usercontrol
public string MyText
{
get{return this.textbox1.Text;} //textbox1 is the name of your textbox
}
private void MyButton_Clicked(/* args */)
{
if (MyEvent!=null)
{
MyEvent(null, null);
}
}
//other codes
}
public class SecondUserControl:UserControl
{
//Public property in your first usercontrol
public string MyText
{
set{this.label1.Text = value;} //label1 is the name of your label
}
//other codes
}
then in your MainForm:
public class MainForm:Forms
{
//Add two instance of the UserControls
public MainForm()
{
this.firstUserControl.MyEvent += MainWindow_myevent;
}
void MainWindow_myevent(object sender, EventArgs e)
{
this.secondUserControl.MyText = this.firstUserControl.MyText;
}
//other codes
}