Setting Focus on a Control within a ControlTemplate in WPF

10,230

Within your control template you can add a Trigger that sets the FocusedElement of the StackPanel's FocusManager to the textbox you want focused. You set the Trigger's property to {TemplateBinding IsFocused} so it fires when the containing control is focused.

Share:
10,230
Bob Wintemberg
Author by

Bob Wintemberg

Updated on July 23, 2022

Comments

  • Bob Wintemberg
    Bob Wintemberg almost 2 years

    In an application I'm working on, we have a bunch of custom controls with their ControlTemplates defined in Generic.xaml.

    For instance, our custom textbox would look similar to this:

    <Style TargetType="{x:Type controls:FieldTextBox}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type controls:FieldTextBox}">
                    <Border BorderThickness="0" Margin="5">
                        <StackPanel ToolTip="{Binding Path=Field.HintText, RelativeSource={RelativeSource TemplatedParent}}">
                            <TextBlock Text="{Binding Path=Field.FieldLabel, RelativeSource={RelativeSource TemplatedParent}}" 
                                       HorizontalAlignment="Left" 
                                       />
                            <TextBox Width="{Binding Path=Field.DisplayWidth, RelativeSource={RelativeSource TemplatedParent}}" 
                                     HorizontalAlignment="Left" 
                                     Text="{Binding Path=Field.Data.CurrentValue, RelativeSource={RelativeSource TemplatedParent}}" 
                                     IsEnabled="{Binding Path=Field.IsEnabled, RelativeSource={RelativeSource TemplatedParent}}"
                                     ContextMenu="{Binding Source={StaticResource FieldContextMenu}}" >
                                <TextBox.Background>
                                    <SolidColorBrush Color="{Binding Path=Field.CurrentBackgroundColor, RelativeSource={RelativeSource TemplatedParent}}"/>
                                </TextBox.Background>
                            </TextBox>
                        </StackPanel>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="Focusable" Value="True" />
        <Setter Property="IsTabStop" Value="False" />
    </Style>
    

    In our application, we need to be able to programatically set the focus on a particular control within the ControlTemplate.

    Within our C# code, we can get to the particular "FieldTextBox" based on our data. Once we have the correct FieldTextBox, we need to be able to set the focus on the actual TextBox contained within the ControlTemplate.

    The best solution I've come up with is to set a name on the primary control in each control template (in this case it's the TextBox), such as "FocusableControl."

    My code (contained in the code-behind for the FieldTextBox) to then set focus on the control would be:

        Control control = (Control)this.Template.FindName("FocusableControl", this);
        if (control != null)
        {
            control.Focus();
        }
    

    This solution works. However, does anyone else know of a solution that would be more efficient than this?

  • Bob Wintemberg
    Bob Wintemberg over 15 years
    I'm not sure if I entirely understand your solution. Could you be more clear or give a short example?
  • jpierson
    jpierson about 13 years
    We might get an accepted answer here if you could elaborate on your solution. I'm trying to do something similar and I'm experimenting with your suggestions but I'm not completely following what the trigger's Value binding would look like amongst other details.