Ashish Singhal
Ashish Singhal

Reputation: 63

How to restrict focus in textbox

I have a dialog with few controls. There is a TextBox named txtControl and two Buttons Accept and Cancel. I want that once the focus is in txtControl, the focus should not go away, until I click on Accept or Cancel button.

If I try to click on any other control without clicking on Accept or Cancel button, then focus should remains in txtControl. Also I don't want to disable or gray out other controls.

Upvotes: 0

Views: 558

Answers (4)

Ramin
Ramin

Reputation: 2133

You might handle OnPreviewMouseDown in the root, whenever focus is on txtControl, and the mouse is not over txtControl, Accept or Cancel;

void mainWindow_previewMouseDown(object sender, MouseEventArg e)
{

     if (txtControl.IsFocusWithin)         
     {
          if (txtControl.IsMouseOver == false ||
             accept.IsMouseOver ==false ||
             cancel.IsMouseOver ==false)
          {
              e.Handle = true;
          }
      }
}

and you might also hadle PreviewKeyDown to see if Tab is Pressed or not.

Upvotes: 1

Andy
Andy

Reputation: 6466

I would create an attached property that looked for the textbox losing Keyboad focus and just force focus back in to the textbox again.

The attached property would be something like this.

  public class TextBoxExtras : DependencyObject
    {
        public static bool GetRetainsFocus(DependencyObject obj)
        {
            return (bool)obj.GetValue(RetainsFocusProperty);
        }

        public static void SetRetainsFocus(DependencyObject obj, bool value)
        {
            obj.SetValue(RetainsFocusProperty, value);
        }

        public static readonly DependencyProperty RetainsFocusProperty =
            DependencyProperty.RegisterAttached("RetainsFocus", typeof(bool), typeof(TextBoxExtras), new PropertyMetadata(false, new PropertyChangedCallback((s, e) =>
                {
                    TextBox textBox = s as TextBox;
                    if (textBox != null)
                    {
                        if (!(bool)e.NewValue && (bool)e.OldValue)
                            textBox.LostKeyboardFocus -= textBox_LostKeyboardFocus;
                        if ((bool)e.NewValue)
                        {
                            textBox.LostKeyboardFocus += textBox_LostKeyboardFocus;
                            textBox.Unloaded += textBox_Unloaded;
                        }
                    }
                })));

        static void textBox_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
        {
            TextBox textBox = sender as TextBox;
            if (textBox != null )
                if (textBox.Focusable)
                    textBox.Focus();
        }

        static void textBox_Unloaded(object sender, RoutedEventArgs e)
        {
            TextBox textBox = sender as TextBox;
            if (textBox != null)
            {
                textBox.LostKeyboardFocus -= textBox_LostKeyboardFocus;
                textBox.Unloaded -= textBox_Unloaded;
            }
        }
    }

And use it in XAML like this, the first textbox is the one that will "retain focus"

<Window x:Class="WpfApplication4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication4"
        Background="Black"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <TextBox local:TextBoxExtras.RetainsFocus="True" Margin="10,10,387,283"/>        
        <TextBox HorizontalAlignment="Left" Height="23" Margin="10,37,0,260" Width="120" />
        <Button Content="Accept" HorizontalAlignment="Left" Margin="10,81,0,0" VerticalAlignment="Top" Width="75" />
    </Grid>
</Window>

Upvotes: 0

Klaus78
Klaus78

Reputation: 11906

You could handle the PreviewLostKeyboardFocus at root level.

In xaml

<Window ... PreviewLostKeyboardFocus="Win_PreviewLostKeyboardFocus">

In C#

private void Win_PreviewLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
    {
        // change focus behavior only when txtControl 
                          // is the element losing focus
        if (e.OldFocus != txtControl)
            return;

                          // if new element with focus is not Accept and is not Cancel, then disable the focus change
        if (e.NewFocus != Accept && e.NewFocus != Cancel)
            e.Handled = true;
    }

Upvotes: 0

Peregrine
Peregrine

Reputation: 4546

This kind of restriction is not a good idea.

How will your app be used by someone who can't use a mouse and uses the tab key to move between controls?

Upvotes: 0

Related Questions