When I click a check box on a Windows Form, it enables a text box and sets the cursor in it ready for input. Code is relatively simple:
private void chkLatte_CheckedChanged(object sender, EventArgs e)
{
if(chkLatte.Checked)
{
txtLatte.Enabled = true;
txtLatte.Focus();
}
else
{
txtLatte.Enabled = false;
txtLatte.Text = "0";
}
}
Now, here's the rub. I have lots of these check boxes so what I want is something like this:
public void setCheckBox(string chkName, string txtName)
{
if (chkName.Checked)
{
txtName.Enabled = true;
txtName.Focus();
}
else
{
txtName.Enabled = false;
txtName.Text = "0";
}
}
Now, I can just call the method and pass the appropriate parameters like this:
private void chkMocha_CheckedChanged(object sender, EventArgs e)
{
setCheckBox(chkMocha,txtMocha);
}
Of course, this won't work: .Checked .Enabled .Focus() etc only work with a check box object and I define chkName as a string
How should I re-write the procedure setCheckBox to overcome this problem?
And why don't you pass the object sender as it is?
I mean something like this:
public void setCheckBox(CheckBox chk, TextBox txt)
{
if (chk.Checked)
{
txt.Enabled = true;
txt.Focus();
}
else
{
txt.Enabled = false;
txt.Text = "0";
}
}
And casting of course:
In the designer you have something like:
private System.Windows.Forms.TextBox txtMocha;
And by this reason you will solve a lot problems.
private void chkMocha_CheckedChanged(object sender, EventArgs e)
{
setCheckBox((CheckBox)sender, txtMocha);
}
Also, I have to say, that the code you give doesn't work... You have supposed it.
If you want pass the parameters as strings, use this:
Get a Windows Forms control by name in C#
One way to solve this is to assign the same handler to all checkboxes even
checkbox1.Check += chk_CheckedChanged;
checkbox2.Check += chk_CheckedChanged;
private void chk_CheckedChanged(object sender, EventArgs e)
{
// do your logic here
}
Related
On the form1 there are buttons with this code. There is a button to go to the disk partition "C", "D", "E", "F" and so on. If the computer has such a disk partition - the button is visible else the button is hidden. How to do it?
private void button10_Click(object sender, EventArgs e)
{
webBrowser1.Navigate(#"C:\");
}
You could use the follwoing code on your Page_Load()
foreach (System.IO.DriveInfo item in System.IO.DriveInfo.GetDrives())
{
if(item.Name == "C:\\")
{
button10.Visible = true;
}
else
{
button10.Visible = false;
}
}
You can use visibility property of a button in this kind of scenario.
for example:
if(condition) {
button.Visible = true;
}
Well since your buttons are hidden by default, you can write a
refresh() method. Inside you can ask if a specific drive exists.
string drive = #"C:\";
if (Directory.Exists(drive))
{
button.Visible = true;
}
Where do I add that code?
You should add the method call or code at a place that will:
be called everytime the Form/Control/Site is refreshed or intialized. Maybe in your Form1.Load Event.
when the buttons get initialized or they need to be seen.
A example for maybe a method you can use:
private void CheckForDisks()
{
if (Directory.Exists(#"C:\"))
{
buttonC.Visible = true;
}
if (Directory.Exists(#"D:\"))
{
buttonD.Visible = true;
}
if (Directory.Exists(#"E:\"))
{
buttonE.Visible = true;
}
// and so on... you can also do this with a loop, look up Adarsh Ravi answer for this
}
You can call this method either in your Form1.Load event like:
privat void Form1_Load(object sender, EventArgs e)
{
this.CheckForDisks();
}
button10_Click() this is a button event of your Form, inside that you can write like this
if(System.IO.DriveInfo.Contains == yourDrive)
{
button10.visible = true;
}
else
{
button10.visible = false;
}
I have tried to code a button such that it is disabled upon form loading however enabled once a textbox has had text entered. My code is below, which is probably familiar:
Public Form()
{
InitializeComponent();
this.button1.enabled = false;
}
private void textbox_TextChanged (object sender, EventArgs e)
{
button1.Enabled = !string.IsNullOrWhiteSpace(textbox.Text);
}
The button indeed loads up disabled, the enabling function doesn't work upon text input and I'm not sure what the issue could be. It is a modal form is that matters. I was wondering if maybe I needed an event listener (although I'm not certain how exactly they work).
Check your Designer.cs file and make sure you have event handler registration there. Something like this:
this.textBox.TextChanged += new System.EventHandler(this.textBox_TextChanged);
Will this work? I can't really see a problem with your code though...
button1.Enabled = textbox.Text != "";
I hope this helps.
May not be the solution to your problem, but this would be the fastest check for one's computer to perform (at least if you let the JIT compiler optimize your code):
button1.Enabled = textbox.Text.Length > 0;
try this
private void Form1_Load(object sender, EventArgs e)
{
button1.Enabled = false;
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(textBox1.Text))
{
button1.Enabled = true;
}
}
You could try either of the following on the TextChanged property of the TextBox :
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (textbox.Text.Length > 0)
{
button1.Enabled = true;
}
else
button1.Enabled = false;
}
or, using the string.IsNullOrEmpty method:
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(textbox.Text))
{
button1.Enabled = true;
}
else
button1.Enabled = false;
}
The the below line:
button1.Enabled = !string.IsNullOrWhiteSpace(textbox.Text);
If it didn't work for you or if you are getting an error, then probably because the IsNullOrWhiteSpace method was introduced in .NET 4
This question already has answers here:
Watermark TextBox in WinForms
(11 answers)
Closed 4 years ago.
I'm currently making a Windows Forms Application on Visual Studio in C# and I'm trying to find a way to have a real hint.
I've found a lot of answers online on how to have some text preset there, Some examples even show how to grey out the text to look like a placeholder, but that's not what I'm looking for.
I want a grayed out text that you don't have to backspace to type something there. So I want it to behave like an HTML placeholder like the "Search Q&A" search bar on stack Overflow.
Is there an easy way to do this, like configuring a property of the textbox in the designer on Visual Studio?
This might be the ugliest code but I think you can improve it.
This following class is merely an extension of the standard TextBox
class PHTextBox : System.Windows.Forms.TextBox
{
System.Drawing.Color DefaultColor;
public string PlaceHolderText {get;set;}
public PHTextBox(string placeholdertext)
{
// get default color of text
DefaultColor = this.ForeColor;
// Add event handler for when the control gets focus
this.GotFocus += (object sender, EventArgs e) =>
{
this.Text = String.Empty;
this.ForeColor = DefaultColor;
};
// add event handling when focus is lost
this.LostFocus += (Object sender, EventArgs e) => {
if (String.IsNullOrEmpty(this.Text) || this.Text == PlaceHolderText)
{
this.ForeColor = System.Drawing.Color.Gray;
this.Text = PlaceHolderText;
}
else
{
this.ForeColor = DefaultColor;
}
};
if (!string.IsNullOrEmpty(placeholdertext))
{
// change style
this.ForeColor = System.Drawing.Color.Gray;
// Add text
PlaceHolderText = placeholdertext;
this.Text = placeholdertext;
}
}
}
Copy/paste to new cs file entitled PHTextBox.cs.
Go to your graphic designer and add a TextBox.
Go to the designer and change the instiantion line for the textbox as follow:
Now compile but before you do, just make sure the textbox is not the first element to get the focus. Add button for that matter.
Have you tried overlapping a label on the textbox?
On the textbox keypress event you can check the length of the textbox.text and set the label.
On the keypress event..
MyLabel.Visible = String.IsNullOrEmpty(MyTextBox.Text);
Of course you might want to set the default text of the label as well as grey it out too.
Issue with this is if your form is re sizable.
What you want to achieve is not native to windows forms.
I know that this is an old question; However I was searching for a way and I found my answer to be best answer to display a prompt text in a TextBox:
1) Create a class .cs file called for example MyExtensions.cs having a namespace called for example 'Extensions'.
2) Create a method in the TextBox called Init(string prompt) that takes the prompt text you want to display inside the TextBox.
3) Let me stop talking and give you the rest of the code for MyExtensions.cs (The entire code):
MyExtensions.cs
using System.Drawing;
using System.Windows.Forms;
namespace Extensions
{
public static class MyExtensions
{
public static void Init(this TextBox textBox, string prompt)
{
textBox.Text = prompt;
bool wma = true;
textBox.ForeColor = Color.Gray;
textBox.GotFocus += (source, ex) =>
{
if (((TextBox)source).ForeColor == Color.Black)
return;
if (wma)
{
wma = false;
textBox.Text = "";
textBox.ForeColor = Color.Black;
}
};
textBox.LostFocus += (source, ex) =>
{
TextBox t = ((TextBox)source);
if (t.Text.Length == 0)
{
t.Text = prompt;
t.ForeColor = Color.Gray;
return;
}
if (!wma && string.IsNullOrEmpty(textBox.Text))
{
wma = true;
textBox.Text = prompt;
textBox.ForeColor = Color.Gray;
}
};
textBox.TextChanged += (source, ex) =>
{
if (((TextBox)source).Text.Length > 0)
{
textBox.ForeColor = Color.Black;
}
};
}
}
}
Now Assume that you have three TextBox's : tbUsername, tbPassword, tbConfirm:
In your Form_Load(object sender, EventArgs e) method initialize your three TextBox's to have their appropriate Prompt Text Messages:
using Extensions;
namespace MyApp{
public partial class Form1 : Form{
private void Form1_Load(object sender,
EventArgs e){
tbUsername.Init("Type a username");
tbPassword.Init("Type a password");
tbConfirm.Init("Confirm your password");
}
}
}
Enjoy! :)
What about this
private bool hasTextBeenTyped;
private void Form1_Load(object sender, EventArgs e)
{
this.ActiveControl = label1;
textBox1.ForeColor = Color.LightGray;
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
hasTextBeenTyped = !String.IsNullOrEmpty(textBox1.Text);
if (hasTextBeenTyped)
{
textBox1.ForeColor = Color.Black;
}
}
private void textBox1_Click(object sender, EventArgs e)
{
if (!hasTextBeenTyped)
{
textBox1.Text = "";
}
}
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
hasTextBeenTyped = true;
}
the this.ActiveControl = label1; is just to take focus away from the text box initially. If something else already does, don't worry about that line.
Please, take a look at my ControlHintManager class, ControlHintInfo type and ControlHintType enumeration. They are written in Vb.Net, but you can get the idea analyzing the source-code, or compile the library to use it in your C# project without any more effort.
My solution has even better behavior than the StackOverflows hint that you mentioned, taking into account that when the control leave focus, the hint-text should be restored if the string remains empty.
Usage is so friendlly:
ControlHintInfo hint1 =
new ControlHintInfo("I'm a hint text.", font (or nul), Color.Gray,
ControlHintType.Persistent);
ControlHintManager.SetHint(TextBox1, hint1);
To acchieve this by your own, one way is calling the Win32 SendMessage function with the EM_SETCUEBANNER message, however, that will produce a too basic hint with poor behavior, not recommendable,
so a proper way to acchieve this is by taking control of the edit-control text by yourself, handling the Control.HandleCreated, Control.Enter, Control.Leave, Control.MouseDown, Control.KeyDown and Control.Disposed events (as you can see in my linked source-code).
Just use a object to keep track of the control's state (forecolor, text, and optionally the font), then use properlly the event-handlers mentioned to set or restore the text and color.
This is a online C# translation of the most-important code of the linked urls if this help you understand it better:
private static void Control_HandleCreated(object sender, EventArgs e) {
InstanceControlHintFields();
Control ctrl = (Control)sender;
ControlHintInfo hintInfo = controlHintsB(ctrl);
SetProperties(ctrl, hintInfo);
}
private static void Control_Enter(object sender, EventArgs e) {
InstanceControlHintFields();
Control ctrl = (Control)sender;
string ctrlText = ctrl.Text;
ControlHintInfo ctrlDefaults = controlHintsDefaults(ctrl);
ControlHintInfo hintInfo = controlHintsB(ctrl);
switch (hintInfo.HintType) {
case ControlHintType.Normal:
if ((ctrlText.Equals(hintInfo.Text, StringComparison.OrdinalIgnoreCase))) {
RestoreProperties(ctrl, ctrlDefaults);
}
break;
}
}
private static void Control_Leave(object sender, EventArgs e) {
InstanceControlHintFields();
Control ctrl = (Control)sender;
string ctrlText = ctrl.Text;
ControlHintInfo ctrlDefaults = controlHintsDefaults(ctrl);
ControlHintInfo hintInfo = controlHintsB(ctrl);
switch (hintInfo.HintType) {
case ControlHintType.Normal:
if ((ctrlText.Equals(hintInfo.Text, StringComparison.OrdinalIgnoreCase))) {
RestoreProperties(ctrl, ctrlDefaults);
} else if (string.IsNullOrEmpty(ctrlText)) {
SetProperties(ctrl, hintInfo);
}
break;
case ControlHintType.Persistent:
if (string.IsNullOrEmpty(ctrlText)) {
SetProperties(ctrl, hintInfo);
}
break;
}
}
private static void Control_MouseDown(object sender, MouseEventArgs e) {
InstanceControlHintFields();
Control ctrl = (Control)sender;
string ctrlText = ctrl.Text;
ControlHintInfo hintInfo = controlHintsB(ctrl);
switch (hintInfo.HintType) {
case ControlHintType.Persistent:
if ((ctrlText.Equals(hintInfo.Text, StringComparison.OrdinalIgnoreCase))) {
// Get the 'Select' control's method (if exist).
MethodInfo method = sender.GetType.GetMethod("Select", BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod, null, {
typeof(int),
typeof(int)
}, null);
if ((method != null)) {
// Select the zero length.
method.Invoke(ctrl, new object[] {
0,
0
});
}
}
break;
}
}
private static void Control_KeyDown(object sender, KeyEventArgs e) {
Control ctrl = (Control)sender;
string ctrlText = ctrl.Text;
ControlHintInfo ctrlDefaults = controlHintsDefaults(ctrl);
ControlHintInfo hintInfo = controlHintsB(ctrl);
switch (hintInfo.HintType) {
case ControlHintType.Persistent:
if ((ctrlText.Equals(hintInfo.Text, StringComparison.OrdinalIgnoreCase))) {
RestoreProperties(ctrl, ctrlDefaults);
} else if (string.IsNullOrEmpty(ctrlText)) {
RestoreProperties(ctrl, ctrlDefaults, skipProperties: { "Text" });
}
break;
case ControlHintType.Normal:
if (string.IsNullOrEmpty(ctrlText)) {
RestoreProperties(ctrl, ctrlDefaults);
}
break;
}
}
private static void Control_Disposed(object sender, EventArgs e) {
RemoveHint((Control)sender);
}
PS: It is Reflection based to support more variety of controls.
I'm trying to make it in my program, if you click on a text box it will select it all. And then if you click it again it deselects it all.
I've tried making it like this..
private void url_MouseDown(object sender, MouseEventArgs e)
{
url.ReadOnly = false;
url.SelectAll();
url.DeselectAll();
}
I know the url.DeselectAll(); is in the wrong spot.
Any help? Thanks in advance!
Clicking the textbox itself clears a selection, so you'd have to do something like this;
bool selected;
private void url_MouseDown(object sender, MouseEventArgs e)
{
url.ReadOnly = false;
if (!selected)
{
selected = true;
url.SelectAll();
}
else
{
selected = false;
url.DeselectAll();
}
}
Your current code first calls
url.SelectAll();
and then immediately calls
url.DeselectAll();
Instead, check the current state of the item you are trying to toggle. It's not clear to me from the question exactly what that is, so in pseudocode:
private bool isSelected = false;
private void url_MouseDown(object sender, MouseEventArgs e)
{
url.ReadOnly = false;
if (isSelected)
{
url.DeselectAll();
}
else
{
url.SelectAll();
}
isSelected = !isSelected;
}
Replace IsDeselected with something that checks whether the current state is deselected or not.
Your code always selects and then deselects again, so your text will always be deselected after mouse down.
Try this instead:
private void url_MouseDown(object sender, MouseEventArgs e)
{
url.ReadOnly = false;
if (url.SelectedText.Length < url.Text.Length) {
url.SelectAll();
} else {
url.DeselectAll();
}
}
I have an editable ComboBox that should contain a path. The user can select several default paths (or enter his own) from a dropdown list, such as %ProgramData%\\Microsoft\\Windows\\Start Menu\\Programs\\ (All Users). The items in the dropdown list contain a short explanation, like the (All Users) part in the former example. Upon selection of such an item, I want to remove this explanation, so that a valid path is displayed in the ComboBox.
I currently strip the explanation out of the string and try to change the text via setting the Text property of the ComboBox. But this doesn't work, the string is parsed correctly, but the displayed text won't update (it stays the same as in the dropdown list, with the explanation).
private void combobox_TextChanged(object sender, EventArgs e) {
//..
string destPath = combobox.GetItemText(combobox.SelectedItem);
destPath = destPath.Replace("(All Users)", "");
destPath.Trim();
combobox.Text = destPath;
//..
}
I found the solution in a similar question, by using BeginInvoke()
Using Nikolay's solution, my method now looks like this:
private void combobox_SelectedIndexChanged(object sender, EventArgs e) {
if (combobox.SelectedIndex != -1) {
//Workaround (see below)
var x = this.Handle;
this.BeginInvoke((MethodInvoker)delegate { combobox.Text = combobox.SelectedValue.ToString(); });
}
}
The workaround is required, since BeginInvoke requires the control to be loaded or shown, which isn't necessarily the case if the program just started. Got that from here.
I suggest you to create PathEntry class to store both Path and its Description.
public sealed class PathEntry
{
public string Path { get; private set; }
public string Description { get; private set; }
public PathEntry(string path)
: this(path, path)
{
}
public PathEntry(string path, string description)
{
this.Path = path;
this.Description = description;
}
}
Then create an instance of BindingList<PathEntry> to store all the known paths and descriptions. Later you can add user-defined paths to it.
private readonly BindingList<PathEntry> m_knownPaths =
new BindingList<PathEntry>();
And update your Form's constructor as follows:
public YourForm()
{
InitializeComponent();
m_knownPaths.Add(new PathEntry("%ProgramData%\\Microsoft\\Windows\\Start Menu\\Programs",
"(All Users)"));
// TODO: add other known paths here
combobox.ValueMember = "Path";
combobox.DisplayMember = "Description";
combobox.DataSource = m_knownPaths;
}
private void combobox_DropDown(object sender, EventArgs e)
{
combobox.DisplayMember = "Description";
}
private void combobox_DropDownClosed(object sender, EventArgs e)
{
combobox.DisplayMember = "Path";
}
You might want to learn more abount DataSource, DisplayMember and ValueMember from MSDN.
this is probably not the most elegant solution, but a simple one for beginners - like me - who don't want to use those InvokeMethods before they understand them a little better.
The boolean is required because when assign a new string(object) to the position in the Items array, the handler is fired again - recursively.
I figured this out just now, since i was working on the exact same problem.
Just sharing :)
bool preventDoubleChange = false;
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (preventDoubleChange){
preventDoubleChange = false;
return;
}
preventDoubleChange = true;
switch (comboBox1.SelectedIndex)
{
case 0:
comboBox1.Items[0] = "ChangeToThisText";
break;
case 1:
comboBox1.Items[1] = "ChangeToThisText";
break;
default:
preventDoubleChange = false;
break;
}
}
...or if you are comfortable using the "Tag" field, you can avoid the whole mess with the boolean. This second variation is also cleaner in my opinion.
public Form1()
{
InitializeComponent();
comboBox1.Items.Add("Item One"); //Index 0
comboBox1.Items.Add("Item Two"); //Index 1
comboBox1.Items.Add("Item Three"); //Index 2
comboBox1.Items.Add("Item Four"); //Index 3
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox1.Tag != null && (int)comboBox1.Tag == comboBox1.SelectedIndex)
return;
switch (comboBox1.SelectedIndex)
{
case 0:
break;
case 1:
comboBox1.Tag = comboBox1.SelectedIndex;
comboBox1.Items[comboBox1.SelectedIndex] = "changed item 2";
break;
case 2:
comboBox1.Tag = comboBox1.SelectedIndex;
comboBox1.Items[comboBox1.SelectedIndex] = "changed item 3";
break;
case 3:
break;
default:
break;
}
}
redfalcon,
You can't change the text this way. What you need to do is get the selectedindex value and then set the Text property. Something like that:
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
var index = DropDownList1.SelectedIndex;
DropDownList1.Items[index].Text = "changed";
}
`
private void combobox_TextChanged(object sender, EventArgs e)
{
//..
string destPath = combobox.SelectedItem.Text;
destPath = destPath.Replace("(All Users)", "");
destPath.Trim();
combobox.SelectedItem.Text = destPath;
//..
}
`