How to get key strockes on parent control to reach child controls that host the actual binding but are not focused

170 Views Asked by At

Please let me know if I need to clarify or post more code!

I could find quite some resources on how to pass keystrokes from a child element to a parent element but not the way around.

I explain my use case:

I have a parent Window (let's call it wndSession) with a couple of focusable controls and a ContentControl which gets its content (a UserControl) assigned using DataTemplate bindings.

<Window.Resources>
    
    <DataTemplate DataType="{x:Type vm:vmLearnModule1}">
        <local:viewLearnModule1 />
    </DataTemplate>
    <DataTemplate DataType="{x:Type vm:vmLearnModule2}">
        <local:viewLearnModule2 />
    </DataTemplate>
    <DataTemplate DataType="{x:Type vm:vmLearnModule3}">
        <local:viewLearnModule3 />
    </DataTemplate>
    <DataTemplate DataType="{x:Type vm:vmLearnResults}">
        <local:viewLearnResults />
    </DataTemplate>
    
</Window.Resources>

And:

<ContentControl Content     = "{Binding learningViewModel}"
                Name        = "contentControl"
                Grid.Row    = "1"
                Grid.Column = "1"
                Height      = "300"
                Margin      = "20, 0, 0, 0" />

Now each UserControl may have different KeyBinginds assigned, and as long as the focus is on the UserControl all works fine.

Example of bindings on a UserControl:

<UserControl.InputBindings>
    <KeyBinding Key="F1" Command="{Binding cmdResultNotKnown}"/>
    <KeyBinding Key="F2" Command="{Binding cmdResultAlmostKnown}"/>
    <KeyBinding Key="F3" Command="{Binding cmdResultKnown}"/>
</UserControl.InputBindings>

My commands are defined all like this sample:

private ICommand _cmdTest;
/// <summary>
/// Test
/// </summary>
public ICommand cmdTest => this._cmdTest ??= new RelayCommand(param => this.doTest(), param => this.canTest);

private bool canTest => true;

private void doTest()
{
    // Some code here
}

Now to the issue:

If I click on any focusable control on the parent window wndSession, the UserControl or its currently focused child will lose Focus and a control of the parent (wndSession) will gain focus (ok, I'd expect that so far).

But because of this, the UserControl will not react to KeyBindings anymore unless I click on any control of the UserControl first. That is not a really good UX...

What I need is a way to:

First i thought about something like to "bubble down" the keystroke to the child controls of wndSession, and especially to the UserControl in the Contentcontrol, in the event that wndSession does not already address the KeyBinding.

But as remarked that would cause many issues. So in order to avoid conflicts (which control can now use it's bindings, etc.) I would suppose that what is needed is to pass the keystroke to a specified target, which in my case would be the UserControl inside the ContentControl if wndSession could not handle the key as no binding is specified.

In short: have wndSession operate as a Router passing all unknown keystrokes (not registered by a KeyBinding) to a Gateway/Proxy (ContentControl/UserControl)

Then there will be only a path down the tree with little risk of conflicts. Currently I fail simulating a keystroke on the target control from parent, so that its KeyBinding can fire.

0

There are 0 best solutions below