views:

922

answers:

6

I have a C# Winforms program with multiple textboxes. I used the properties for each box to place text in them, explaining to the user what value goes in them. I want the text to highlight whenever a user selects that box. By either tabbing or mouse click. I won't have to do this if there's a way to display what value goes in the textbox somewhere outside of it.

I tried the Textbox.select method but it had no effect. The same with this.

Here's a Screenshot of my program.

My Code:

    private void grapplingText1_MaskInputRejected(object sender, MaskInputRejectedEventArgs e)
    {
        grapplingText1.SelectionStart = 0;
        grapplingText1.SelectionLength = grapplingText1.Text.Length;

Will this do, or is more required?

+4  A: 

I think .select will work if you know the text amount you want to select.

Try .SelectAll(); It should work for you

Redburn
+2  A: 

You need to use the TextBox.Focus() to get the focus on your control, and if doesn't automatically work, then just call the SelectAll() method on the Enter() event.

private TextBox1_Enter(object sender, EventArgs e) {    
    TextBoxTextHighlight(sender, null);
}

private TextBox2_Enter(object sender, EventArgs e) {
    TextBoxTextHighlight(sender, null);
}

private TextBox3_Enter(object sender, EventArgs e) {
    TextBoxTextHighlight(sender, null);
}

// And so forth...

private void TextBoxTextHighlight(object sender, EventArgs e) {
    (sender as TextBox).SelectAll();
}

This method will allow you to call it from any TextBoxX_Enter() event handler.

Otherwise, you even could create a new UserControl, call it whatever you want upon creation, then, when created into your project, edit the code and replace the inheritence of UserControl class by the TextBox class, then define within it the default behaviour you would like to have on the Enter() event, like this call to the SelectAll() method, and make it protected virtual, and within the constructor, you may subscribe the event handler like so:

public partial class CustomTextBox : TextBox {
    public CustomTextBox() 
        : base() {
        this.Enter += new EventHandler(Enter);
    }

    protected virtual Enter(object sender, EventArgs e) {
        this.SelectAll();
    }
}

I wrote it on the fly, so perhaps a few modifications are required, but you may get the idea. But I do not advise you to do so unless it's really worthy doing it for your proper situation. The simpler the better, and the simplest is to create an event handler for each of your form's TextBoxes and then call the TextBoxTextHighlight() method.

Will Marcouiller
I do this for each text box?
Slateboard
Double-clicking the event Enter() from the Property Window Event List for each TextBox will allow you to write the line of code in TextBox1_Enter() event handler and to propagate the functionality of SelectAll() without too much effort. So yes, for each TextBox.
Will Marcouiller
+1  A: 

Suppose that your textbox´s name is 'MyTextBox'

You can write the method to handle the Focus event:

private void MyTextBox_GotFocus(object sender, EventArgs e)
{
    MyTextBox.SelectionStart = 0;
    MyTextBox.SelectionLength = MyTextBox.Text.Length;
    MyTextBox.Select();
}

You´ll need to add the event handler too:

this.MyTextBox.GotFocus += new System.EventHandler(this.MyTextBox_GotFocus);

This should work...

EDIT

You can use the same method for other textbox, just add the event handler:

this.MyTextBox2.GotFocus += new System.EventHandler(this.MyTextBox_GotFocus);
this.MyTextBox3.GotFocus += new System.EventHandler(this.MyTextBox_GotFocus);
this.MyTextBox4.GotFocus += new System.EventHandler(this.MyTextBox_GotFocus);
//...
Javier Morillo
Does it replace the code already entered?
Slateboard
Yes it does, at least, I have made a test with this code, and it works fine =)
Javier Morillo
I replace all instances of mytextbox with the names of my actual textboxes, right?
Slateboard
Right, MyTextBox is just the name I´ve chose, just as an example. BUT you don´t need to change the name of the method MyTextBox_GotFocus.
Javier Morillo
I would really go with watermarking like Matt suggested then doing it the hard way with events. I've updated my post how you should do it and it really seems the best way (as addition to use `Label`/`ToolTip`)
MadBoy
Thanks for clarifying that.
Slateboard
You are welcome =)
Javier Morillo
+2  A: 

Typically, if you want to explain to the user what goes in a textbox, you place a Label control directly above it, (or to the side).

Sometimes though, to save screen real-estate, you can put a description of the text inside of the textbox itself. This is called a watermark.

Matt Brunell
Well the textboxes currently display text descriptions within them, so is that what you mean by a watermark?
Slateboard
Watermark is like a builtin text that you won't have to take care of when user tries to type in stuff into that TextBox. It always shows up when TextBox is empty, and it's gone when there's Text Inside.
MadBoy
Right. A good example of the watermark is the search textbox in the upper right of stackoverflow. The disadvantage of the watermark is that you can't tell what the value is supposed to mean when it is filled in. Looking at your screenshot, I would have to recomend that you use Label controls, placed directly above the textboxes.
Matt Brunell
+1 I like your suggestion
Javier Morillo
+6  A: 

How about you assign ToolTip to TextBox and put all the "talk what textbox is for" inside that?

Just drag & drop ToolTip inside the Form. And then in each TextBox properties you should have additional entry in Misc section ToolTip on toolTip1 (or whatever it's name will be if you rename it).

Then when user hovers over TextBox (Read Only/Disabled TextBox doesn't seems to display ToolTips) and stops there for 1 second ToolTip should show with proper info.

You can eventually or even better have a Label next to TextBox saying what is is, but having a ToolTip is also a good idea to explain more information to user thru that.

For doing stuff with WaterMark so you don't have to go the long way by setting the events, taking care of SelectAll etc you could do it like this. Create new watermark.cs file and replace it with this code. Make sure you have changed namespace to match your program namespace.

#region
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

#endregion

namespace Watermark {
    public static class TextBoxWatermarkExtensionMethod {
        private const uint ECM_FIRST = 0x1500;
        private const uint EM_SETCUEBANNER = ECM_FIRST + 1;
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, uint wParam, [MarshalAs(UnmanagedType.LPWStr)] string lParam);
        public static void SetWatermark(this TextBox textBox, string watermarkText) {
            SendMessage(textBox.Handle, EM_SETCUEBANNER, 0, watermarkText);
        }
    }
}
   internal class WatermarkTextBox : TextBox {
    private const uint ECM_FIRST = 0x1500;
    private const uint EM_SETCUEBANNER = ECM_FIRST + 1;
    private string watermarkText;
    public string WatermarkText {
        get { return watermarkText; }
        set {
            watermarkText = value;
            SetWatermark(watermarkText);
        }
    }
    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, uint wParam, [MarshalAs(UnmanagedType.LPWStr)] string lParam);
    private void SetWatermark(string watermarkText) {
        SendMessage(Handle, EM_SETCUEBANNER, 0, watermarkText);
    }
}

In your Form you activate it like this:

textBoxYourWhatever.SetWatermark("Text that should display");

It stays there as long the TextBox is empty. When users gets into TextBox text disappears. It appears again when TextBox is cleaned (either by user or automatically). No need for any special events etc.

EDIT:

I've added also internal class WaterMarkTextBox which gives you an option to simply use new WaterMarkTexBox that becomes available in Designer. Then drag and drop it to your designer and use it. It behaves like normal textbox just gives you additional field WaterMarkText.

I still prefer the first method thou. Doesn't make you rebuild your gui again.

MadBoy
+1 I´ll keep your example, I find it very usefull =)
Javier Morillo
I tried it and the error I got stated: Extension methods must be defined in a top level static class; TextBoxWatermarkExtensionMethod is a nested class What am I doing wrong? Also, .SetWatermark isn't listed on the autocomplete.
Slateboard
I'm guessing, from that error, that you have put the Extensions class inside of another class. You can't do this. It must be a top level class. Once you do this, and it compiles, then SetWatermark will show up in the IntelliSense.
Alastair Pitts
I've edited code so that you can just create new class (click on Solution Explorer, then right click on your Program and then ADD -> Class. Replace everything in it with the code. Change Watermark namespace to match your program namespace.
MadBoy
+1 like your code. Didn't know about this method
Martijn
A: 

The simplest way to show some additional information when hovering over an item would be to use a Tooltip. I've tried a similar watermark approach but having found there's no immediate way to implement it the Tooltip seemed to be a suitable alternative.

You can see how to implement it at the following link: Implementing a tooltip

Jamie Keeling
Check my answer for immediate way implementing watermark. Easy to implement and use.
MadBoy
Awesome, nice work.
Jamie Keeling