#1,075 – Triggering on IsKeyboardFocusWithin Property

You can set up a trigger that fires whenever a control’s IsKeyboardFocused property becomes truechanging the value of some other property when the control gains keyboard focus.

You can also trigger on the IsKeyboardFocusWithin property.  This property will get set to true for an element when any child of that element has keyboard focus.

In the example below, we set the background color of either StackPanel when any element within the StackPanel has focus.  This technique may be useful when you want to keep track of what section of a window the user is working in and do something based on that knowledge.

    <Window.Resources>
        <Style x:Key="HoneydewFocus" TargetType="StackPanel">
            <Style.Triggers>
                <Trigger Property="IsKeyboardFocusWithin" Value="true">
                    <Setter Property="Background" Value="Honeydew"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    
    <StackPanel>
        <StackPanel Orientation="Horizontal" Margin="10"
                    Style="{StaticResource HoneydewFocus}">
            <Button Content="Click Me" VerticalAlignment="Center"/>
            <TextBox Width="200" Height="25" Margin="10"/>
        </StackPanel>

        <StackPanel Orientation="Horizontal" Margin="10"
                    Style="{StaticResource HoneydewFocus}">
            <Button Content="Or Me" VerticalAlignment="Center"/>
            <TextBox Width="200" Height="25" Margin="10"/>
        </StackPanel>
    </StackPanel>

1075-001

1075-002

#847 – Default Button Behavior Depends on Focus

When you set the IsDefault property of a Button to true, the user can activate the button by pressing the ENTER key.

The default behavior of a Button, however, will depend on which control in the window has focus when the user presses ENTER.  If the control that has focus can itself handle the ENTER key, that control will activate when ENTER is pressed, rather than a Button that has IsDefault set to true.

In the example below, the second TextBox has AcceptsReturn set to true and the “Save” button has IsDefault set to true.  Because both the second TextBox and the Cancel button can themselves handle the ENTER key, the “Save” button will only activate on ENTER if the first TextBox has focus when ENTER is pressed.

847-001

847-002

#643 – Disabled Controls Cannot Get Focus

When a control is disabled, i.e. its IsEnabled property is set to false, the user cannot give the control keyboard focus by clicking on it.  The control also cannot gain focus by use of the tab key.  Disabled controls cannot get focus, even if both their Focusable and IsTabStop properties are set to true.

    <StackPanel Orientation="Vertical">
        <StackPanel Orientation="Horizontal">
            <TextBox Text="IsEnabled=true" IsEnabled="True" Width="140" Margin="10"/>
            <TextBox Text="IsEnabled=false" IsEnabled="False" Width="140" Margin="10"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal">
            <Button Content="IsEnabled=true" IsEnabled="True" Margin="10"/>
            <Button Content="IsEnabled=false" IsEnabled="False" Margin="10"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal">
            <ComboBox IsEnabled="True" Margin="10" SelectedIndex="0">
                <ComboBoxItem Content="McClellan"/>
                <ComboBoxItem Content="Hooker"/>
                <ComboBoxItem Content="Meade"/>
            </ComboBox>
            <ComboBox IsEnabled="False" Margin="10" SelectedIndex="0">
                <ComboBoxItem Content="McClellan"/>
                <ComboBoxItem Content="Hooker"/>
                <ComboBoxItem Content="Meade"/>
            </ComboBox>
        </StackPanel>
        <StackPanel Orientation="Horizontal">
            <Label Content="IsEnabled=true" IsEnabled="True" Margin="10"/>
            <Label Content="IsEnabled=false" IsEnabled="False" Margin="10"/>
        </StackPanel>
    </StackPanel>

#639 – Default Tab Order Is Sensible

In WPF, you can use the Tab key to cycle through all of the focusable controls in a window, changing which control currently has focus.

You normally don’t need to worry about the tab order for controls in a window or page because WPF sets the tab order to match the logical tree.  If you start an application and press the Tab key, the first control in the logical tree will receive focus.

If you then continue to press Tab, each control in the logical tree that has its IsTabStop property set will receive focus.  The order will match the logical tree, starting at the top-level parent and working in a depth-first fashion through all child controls.

In the example below, we have several nested StackPanelin a window.  The numbers indicate the effective tab order.

#623 – Focusable Property Indicates Whether a Control Can Receive Focus

All controls that derive from UIElement have a Focusable property that indicate whether or not they are allowed to have focus.  This property defaults to a value that makes sense for each type of control, given whether a control is meant to allow a user to interact with it by pressing keys.

Here’s a summary of some common user interface elements, with their default values for Focusable.

Elements that have Focusabletrue by default:

  • Button
  • Calendar
  • ComboBox
  • DataGrid
  • DatePicker
  • ListBox
  • RichTextBox
  • Slider
  • TabControl
  • TextBox
  • TreeView
  • Window

Elements that have Focusablefalse by default:

  • Canvas
  • DockPanel
  • Grid
  • Image
  • Label
  • ProgressBar
  • ScrollBar
  • Separator
  • Subclasses of Shape (Ellipse, Line, Path, Polygon, Polyline and Rectangle)
  • StackPanel
  • TextBlock
  • UniformGrid
  • Viewport3D
  • WrapPanel

#311 – Giving Focus to a Control, Part II

You can give focus to a specific control at run-time using the Keyboard.Focus static method.  You can also give focus to any control that inherits from UIElement using the control’s Focus method.

		public MainWindow()
		{
			this.InitializeComponent();

            this.Loaded += new RoutedEventHandler(MainWindow_Loaded);

		}

        void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            // On startup, set focus to first TextBox in window
            txtFirst.Focus();
        }

The difference between these two methods is:

  • Keyboard.Focus just sets keyboard focus
  • UIElement.Focus tries to set keyboard focus.  If the control fails to get keyboard focus, the method sets logical focus to the control

#310 – Give a Control Logical Focus

You can give a control the keyboard focus using the static Keyboard.Focus method.  If you want to instead give a control the logical focus, you can use the FocusManager.SetFocusedElement static method.  (In the System.Windows.Input namespace).

                // Give logical focus to txtFirst TextBox
                DependencyObject focusScope = FocusManager.GetFocusScope(txtFirst);
                FocusManager.SetFocusedElement(focusScope, txtFirst);

If you do this in an application with multiple windows and you set logical focus for a control in the inactive window, you’ll see that it does not get keyboard focus.  You can continue entering text in a control in the active window.  But when you switch back to the inactive window, you’ll see that the control does get keyboard focus.