Question

I noticed that KeyTrigger does not fire when used inside a Popup control.

<UserControl x:Class="SilverlightBindingTest.iTest"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         mc:Ignorable="d"
         d:DesignHeight="300" d:DesignWidth="400"
         xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
         xmlns:ii="clr-namespace:Microsoft.Expression.Interactivity.Input;assembly=Microsoft.Expression.Interactions"
         xmlns:ei="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions">

    <Grid x:Name="LayoutRoot" Background="White">
        <Popup IsOpen="True">
            <i:Interaction.Triggers>
                <ii:KeyTrigger Key="Enter">
                    <ei:ChangePropertyAction TargetName="alert" PropertyName="Visibility" Value="Visible" />
                </ii:KeyTrigger>
            </i:Interaction.Triggers>

            <StackPanel>
                <TextBox />
                <TextBlock Text="hi" x:Name="alert" Visibility="Collapsed"/>
            </StackPanel>
        </Popup>
    </Grid>
</UserControl>

When you remove the Popup part, this works as expected ("hi" appears when you press Enter).

What's going on here? I can't think of a reason why KeyTrigger should be failing.

Was it helpful?

Solution

What's going on here?

Maybe the KeyTrigger code adds the listener on the application root, in which case it would never bubble up from the Popup control (since it's not in the visual tree). Well, no problem, I'll just check the source, and ... oh wait, the source is secret and proprietary. Thanks Microsoft!

Anyway, here is a key-trigger that attaches the listener to the TriggerBase.AssociatedObject, so that it will work inside a popup.

public class KeyTriggerThatWorks : TriggerBase<FrameworkElement>
{
    private FrameworkElement _target;

    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.Loaded += (sender, args) =>
        {
            _target = AssociatedObject;
            _target.KeyDown += new KeyEventHandler(Visual_KeyDown);
        };  
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        _target.KeyDown -= new KeyEventHandler(Visual_KeyDown);   
    }

    public Key Key { get; set; }

    void Visual_KeyDown(object sender, KeyEventArgs args)
    {
        if (Key == args.Key)
            InvokeActions(Key);
    }  
}

Also, you still have attach this to a child of the Popup, rather than to the Popup itself. The KeyDown handler does not fire when attached to Popup, for reasons known only to those privy to Microsoft's secret, proprietary code.

<Popup IsOpen="True">
    <StackPanel>

        <i:Interaction.Triggers>
            <local:KeyTriggerThatWorks Key="Enter">
                <ei:ChangePropertyAction TargetName="alert" PropertyName="Visibility" Value="Visible" />
            </local:KeyTriggerThatWorks>
        </i:Interaction.Triggers>

        <TextBox />
        <TextBlock Text="hi" x:Name="alert" Visibility="Collapsed"/>
    </StackPanel>
</Popup>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top