tags:

views:

281

answers:

1

.NET 2.0 is used in my project.

In my project there is an UserControl which includes a NumericUpDown ctrl, and its valid value range is from 10 to 100,

so if user inputs 200 in NumericUpDown ctrl, then its value will changed to 100 automatically after the focus changed to other ctrl, it looks a little bit curious for customer, because they may click the OK button after input 200 in the NumericUpDown ctrl, they need a message box that tells them the value they input is not in the range.

But the question is the value for NumericUpDown will change automatically after the focus changed if the value input is out of its range.

So how to implement this?


Sameh Serag, this is the code I have tested. I have add a button on the form but did nothing. The result for me is after I input 200 and click the button, only a messagebox with value 100 is shown. After I input 200 and press the tab key, it will only show a messagebox with the value 200 and the text value in NumericUpDown is changed to 100. So curious :-) Anyway thank you very much for your help! BTW, the .Net framework version is 2.0 with sp2 for me.

public partial class Form1 : Form
    {
        TextBox txt;

        public Form1()
        {
            InitializeComponent();

            txt = (TextBox)numericUpDown1.Controls[1];
            txt.Validating += new CancelEventHandler(txt_Validating);
        }

        void txt_Validating(object sender, CancelEventArgs e)
        {
            MessageBox.Show(txt.Text);
        }
    }
+2  A: 

The trick is to get the textbox embedded within the numeric updown control, and handle its Validating event.

Here is how to get it done:

Creat a dummy form and add a numeric updown control and some other controls, and when the numeric unpdown control looses the focus, the text of the form will be set to the value that the user entered.

Here it the code of what I have done:

public partial class Form1 : Form
    {
        TextBox txt;
        public Form1()
        {
            InitializeComponent();
            txt = (TextBox)numericUpDown1.Controls[1];//notice the textbox is the 2nd control in the numericupdown control
            txt.Validating += new CancelEventHandler(txt_Validating);
        }
        void txt_Validating(object sender, CancelEventArgs e)
        {
            this.Text = txt.Text;
        }
    }

EDIT:

@Carlos_Liu: Ok, I can see now the problem, you can achieve this with the TextChanged event, just save the value in a dummy variable and reuse it at txt_Validating, but be cautious, don't update this variable unless the textbox is focused.

Here is the new sample code:

public partial class Form1 : Form
{
    TextBox txt;
    string val;
    public Form1()
    {
        InitializeComponent();
        txt = (TextBox)numericUpDown1.Controls[1];//notice the textbox is the 2nd control in the numericupdown control
        txt.TextChanged += new EventHandler(txt_TextChanged);
        txt.Validating += new CancelEventHandler(txt_Validating);
    }

    void txt_TextChanged(object sender, EventArgs e)
    {
        if (txt.Focused) //don't save the value unless the textbox is focused, this is the new trick
            val = txt.Text;
    }
    void txt_Validating(object sender, CancelEventArgs e)
    {
        MessageBox.Show("Val: " + val);
    }
}

EDIT#2

@Carlos_Liu: If you need the entered value to be kept, still there is a trick for doing so: @ the Validating event of the textbox, check the value, if it is not within the range, cancel loosing the focus!

Here is a new version of the code:

public partial class Form1 : Form
{
    TextBox txt;
    string val;
    public Form1()
    {
        InitializeComponent();
        txt = (TextBox)numericUpDown1.Controls[1];
        txt.TextChanged += new EventHandler(txt_TextChanged);
        txt.Validating += new CancelEventHandler(txt_Validating);
    }

    void txt_TextChanged(object sender, EventArgs e)
    {
        if (txt.Focused)
            val = txt.Text;
    }
    void txt_Validating(object sender, CancelEventArgs e)
    {
        int enteredVal = 0;
        int.TryParse(val, out enteredVal);
        if (enteredVal > numericUpDown1.Maximum || enteredVal < numericUpDown1.Minimum)
        {
            txt.Text = val;
            e.Cancel = true;
        }
    }
}
Sameh Serag
It seems dose not work because when enter the textbox's validating event, the value has been cut off according to NumericUpDown's min/max value
Carlos_Liu
No, it does work for me. Make sure you are handling the **Validating** not the **Validated** event. Try it simply alone then embed it in your project.
Sameh Serag
Have you tried to input a value larger than numericUpDown1's maximum value? Suppose that max value of numericUpDown1 is 100, if you input 200, then txt_Validating will be triggered after numericUpDown1 lose focus, and you can popup the txt's text as following ###void txt_Validating(object sender, CancelEventArgs e) { MessageBox.Show(txt.Text); } ###you will see its value has already been cut off to 100
Carlos_Liu
I checked it again (with message boxes) and it works properly!. I handled the **Validating** and **Validated** events of the textbox, and I handled the **Validating** event of the numericUpDown with the same event handler of the textbox, and I was able to see 3 messageboxes: the first (txt.Validating) with the real value, the 2nd (txt.Validated), and the 3rd (numericUpdown1.Validating) with the cut off value. What you have said only happens if the txt_Validating is the event handler for the numericUpdown1 itself not the embedded textbox. Would you mind showing us your actual code?
Sameh Serag
@Carlos_Liu: Perhaps the issue is that you're popping up a message box during the validating event, causing the control to lose focus (and when it looses focus, it clobbers your entry)?
Scott Smith
If it is the message box causing the control to lose focus, try showing a tooltip instead
benPearce
Awesome trick. I was able to remove a nasty NumericUpDown subclass for capturing when the user typed into the textbox with just these few lines of code.
Brad Bruce
Thanks for everybody's help, especially thanks Sameh Serag! But your answer does not solve my problem, because the value will still be cut after the NumericUpDown loses focus even if you can get the value you input. Anyway I think I have to use textbox instead...
Carlos_Liu
@Carlos_Liu: Still you can do it with numeric updown! check my updated version of the code above.
Sameh Serag
@Sameh Serag: After using your new code, I can't focus on other control if the value input in NumericUpDown is larger than its maximum. After removing this line ##e.Cancel = true;## it seems work more normally (but there are still some issues). Any way thanks for your help
Carlos_Liu