views:

273

answers:

4

I have a simple situation (.NET2): a texbox1 on a UserControl1(or Form1).

I want to unfocus(leave) the texbox when I click on the usercontrol/form(focus the usercontrol/form instead): alt text

I do the following on the UC/form:

      Protected Overrides Sub OnMouseClick _
          (ByVal e As System.Windows.Forms.MouseEventArgs)
        MyBase.OnMouseClick(e)
        Me.Focus()
      End Sub

Why does it not work on the child textbox, but works very well on the non-child one(focus on textBox2 then click on the panel removes the focus from the textBox2)?

Real project Window

alt text

A: 

It is better simply to trap the mouse event on your usercontrol and set focus on itself. This will automatically take the focus out of textbox.

Ravia
this is **exactly** what I do.
serhio
+2  A: 

You are battling built-in behavior of both the Form and the UserControl class. They were written to never accept the focus if they contain any child controls, they automatically move the focus to a child instead. Built-in behavior for the ContainerControl class, the base class for both. GroupBox is another one.

That makes a lot of sense if you think about it: neither is capable of showing that they have the focus nor is there anything useful that would happen when the user starts typing.

Don't fix this, it will just deeply confuse the user.

Hans Passant
thank you nobugs. In the real project I have in the panel some texboxes that are "3d" when focused(edit mode) and flat when not(preview mode). My scope is transform it in flat mode when the user will end the editing and will click somewhere else (usually on the panel)
serhio
No, the user will click on something that looks clickable. A control, not a panel. There's nothing that invites a click on a panel, it just looks like "background". You'd have to paint a bulls-eye on it to make it obvious. Then it still doesn't make sense to the user, there's no clue what to do next.
Hans Passant
@nobugs: take a look on the real project window that is supposed to use the click on the panel. This is a time-graphic of a bus driver(x= hours, y = stations). User double clicks on a yellow label in order to modify the hour and edits the new hour. How, in order to validate it can click anywhere else. How it work with the mouse, the most convenable place to click is the background panel. More that then, the `Focus()` method on the panel works on the other(non child) controls, even if the panel have any child control on it...
serhio
Simple, add an Update or OK button.
Hans Passant
@nobugs: I would like to do simple: edits, leaves(clicks anywhere outside the button on the panel) - follows validation and saving.
serhio
+1  A: 

It looks like you're trying to partially duplicate the behavior you see in a Chart in Excel. You can click on any object in the chart, and it is selected (has focus), but if you click outside the chart area, but still within the chart object, nothing is selected.

This would be very familiar behavior to people who are used to charts in Excel.

Basically, you need a control that will normally accept the focus. I've wrestled with this same problem in the past. The best solution I have come up with (and by 'best' I don't mean it's actually good) is to create a blank textbox, and position it behind your UserControl. Then your code for clicking on the usercontrol looks like this:

Protected Overrides Sub OnMouseClick _
          (ByVal e As System.Windows.Forms.MouseEventArgs)
        MyBase.OnMouseClick(e)
        myFakeTextBox.Focus()
End Sub

The user never sees this textbox getting the focus. All they see is that now nothing is selected in the form, and they are free to go about their business.

This method works just fine, but from a maintenance standpoint it is a bit of a headache, as you have to remember that the phony textbox is there and what it's good for.

Stewbob
you will have also to move your textbox wihen Scrolling because if you scrolls somewhere and will click on the panel the scrolling position should not change...
serhio
Yes, good point. I've never implemented this where scrolling was required.
Stewbob
+2  A: 
  1. Add a new panel control to your form (somewhere out of the way) and resize it to 0,0
  2. Do NOT set Visible = false on this panel.
  3. In your form add a standard MouseClick event handler as follows:

    private void Form1_MouseClick(object sender, MouseEventArgs e)
    {
        // Uncomment if in scrollable control
        //Point scrollPos = new Point(this.AutoScrollPosition.X, -this.AutoScrollPosition.Y);
        newPanel.Select(); 
        // Uncomment if in scrollable control
        //this.AutoScrollPosition = scrollPos;
    
    
    }
    
  4. Now, when you click anywhere on your main form, any input control will lose focus and you will be able to handle the usual Validating events etc.
Ash
thank you Ash, it works :)
serhio
Glad to help :) Looks like an interesting control you're building.
Ash