Set focus to child element inside control template

1.8k Views Asked by At

I have a control template for a control derived from CheckComboBox control of Extended WPF Toolkit (almost the same as standart ComboBox). I'm trying to track when key is pressed on this control while its dropdown part is open to modify some of its properties. But when I open dropdown and press any key nothing happens (breakpoint is hit neither inside OnKeyDown nor inside OnPreviewKeyDown overriden methods). They start to being hit only if I previously clicked on a control inside dropdown part. So how could I make them work even if child control doesn't have focus or how can I set focus to child control when drop down is open. For the latter I tried to use trigger in ControlTemplate.Triggers collection but it can't find child element neither with {x:Reference ChildControl} nor with {Binding ElementName=ChildControl}.

Here is a XAML snippet for template

<ControlTemplate x:Key="MyTemplate" TargetType="{x:Type wpfApplication2:DropDownMultiSelector}">
        <ControlTemplate.Triggers>
            <!--This one doesn't work-->
            <Trigger Property="IsDropDownOpen" Value="True">
                <Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName=PART_Popup}" />
            </Trigger>
        </ControlTemplate.Triggers>
        <Grid x:Name="MainGrid" SnapsToDevicePixels="True">
            <Popup x:Name="PART_Popup" AllowsTransparency="True" IsOpen="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Margin="1" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom" StaysOpen="False">
                <Grid MinWidth="{Binding ActualWidth, ElementName=MainGrid}">
                    <Border x:Name="DropDownBorder" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" MaxHeight="{Binding MaxDropDownHeight, RelativeSource={RelativeSource TemplatedParent}}">
                        <ScrollViewer x:Name="DropDownScrollViewer">
                            <Grid RenderOptions.ClearTypeHint="Enabled">
                                <Canvas HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0">
                                    <Rectangle x:Name="OpaqueRect" Fill="{Binding Background, ElementName=DropDownBorder}" Height="{Binding ActualHeight, ElementName=DropDownBorder}" Width="{Binding ActualWidth, ElementName=DropDownBorder}"/>
                                </Canvas>
                                <ContentControl x:Name="ChildControl" Content="{TemplateBinding ChildItemsControl}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                            </Grid>
                        </ScrollViewer>
                    </Border>
                </Grid>
            </Popup>
            ...
2

There are 2 best solutions below

0
On BEST ANSWER

What helped me is setting focus to control itself, not to its subcontrol.

<ControlTemplate.Triggers>
    <Trigger Property="IsDropDownOpen" Value="True">
        <Setter Property="FocusManager.FocusedElement" Value="{Binding RelativeSource={RelativeSource Self}}" />
    </Trigger>
</ControlTemplate.Triggers>
4
On

Liste to Loaded event and set focus.

Here is an example how to handler events in XAML :)

<Grid>
    <!–Define the button content –>
    <Button Width="133" Height="24" Name="btnExitApp" Click="btnExitApp_Clicked" Content="Exit Application"/>
    <!–The C# implementation of the button's Click event handler. –>
    <x:Code>
        <![CDATA[            
            private void btnExitApp_Clicked(object sender, RoutedEventArgs e)
            {
                // Get a handle to the current app and shut it down.
                Application.Current.Shutdown();
            }
        ]]>
    </x:Code>
</Grid>

Yes you can write code in XAML! :)