Question

I have tabItems with TextBox on their headers. I use LostFocus and MouseDoubleClick events to set the text to the TextBox.

<TabControl>
                <TabItem Width="50">
                    <TabItem.Header>
                        <TextBox Text="text" IsReadOnly="True" LostFocus="TextBox_LostFocus" MouseDoubleClick="TextBox_MouseDoubleClick"/>
                    </TabItem.Header>
                </TabItem>
</TabControl>

    private void TextBox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
    {
        TextBox text_box = sender as TextBox;
        if (text_box == null) { return; }

        text_box.IsReadOnly = false;
        text_box.SelectAll();
    }

    private void TextBox_LostFocus(object sender, RoutedEventArgs e)
    {
        TextBox text_box = sender as TextBox;
        if (text_box == null) { return; }

        text_box.IsReadOnly = true;
    }

LostFocus event happens if only you click on the TabItem header area outside the TextBox or on enother TabItem. Clicking the tab item content area doesn't fire lost focus event.

How to make the TextBox to lose focus when user click any area outside the TextBox?

Was it helpful?

Solution

To lost Focus, in other word to get Focus at inside tab content(target):

  1. Focusable of the target is set as true
  2. The target should be hit testable. Background of the target should not be null.
  3. Add event handler to PreviewMouseDown event(NOTE: NOT MouseDown) to react to mouse click. If you except 3 step, you application will react only to TAB key.

    <TabControl>
        <TabItem Width="50">
            <TabItem.Header>
                <TextBox 
                    Text="text" IsReadOnly="True" 
                    LostFocus="TextBox_LostFocus"
                    MouseDoubleClick="TextBox_MouseDoubleClick"/>
            </TabItem.Header>
            <Border Focusable="True" Background="Transparent" PreviewMouseDown="Border_PreviewMouseDown"/>
        </TabItem>
    </TabControl>
    
    
    private void Border_PreviewMouseDown(object sender, MouseButtonEventArgs e)
    {
        var uiElement = sender as UIElement;
        if (uiElement != null) uiElement.Focus();
    }
    

OTHER TIPS

To lose focus, an element must first have focus. Perhaps an alternative could be to give your element focus in an appropriate place when your elements are initialized, for example:

Change

<TextBox Text="text" IsReadOnly="True" LostFocus="TextBox_LostFocus" MouseDoubleClick="TextBox_MouseDoubleClick"/>

To

<TextBox x:Name="MyTextBox" Text="text" IsReadOnly="True" LostFocus="TextBox_LostFocus" MouseDoubleClick="TextBox_MouseDoubleClick"/>

And in your constructor use the FocusManager to set the focused element:

...
FocusManager.SetFocusedElement(MyTextBox.Parent, MyTextBox);
...

Focus Overview on MSDN is a good resource, it is also important to distinguish between keyboard focus and logical focus!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top