Hank
Hank

Reputation: 2616

How to have interaction behavior work on a UserControl

I have the following UserControl that has an attached behavior on it. At the moment I have to select one of the DataGrid items in order for it to run the behavior.

Only guessing here but it's kind of understandable because these containers are not focusable or are not supposed to register keyboard events, so it goes to the next child available???

I could place this functionality on the window however this UserControl can get swapped out with another UserControl and I prefer for it not be be lying around. This is just a unique case in my app where the only thing on the window is the DataGrid and I don't necessarily want to select a DataGrid item to begin the behavior.

My question is: Is it possible to get the following behavior to work? Either on the UserControl, Grid or maybe some other control that would permit this.

<UserControl x:Class="UserManagement.LaunchPad"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:helpers="clr-namespace:UserManagement.Helpers"
             xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
             xmlns:sys="clr-namespace:System;assembly=mscorlib">

    <i:Interaction.Behaviors>
        <helpers:OpenPopupBehaviors FindPopupObject="{Binding ElementName=PopupFind}" 
                                    GotoPopupObject="{Binding ElementName=PopupGoto}" />
    </i:Interaction.Behaviors>

    <Grid>
        <DockPanel>
            <DataGrid />
        </DockPanel>
        <Popup Name="PopupGoto" />
        <Popup Name="PopupFilter "/>
    </Grid>
</UserControl>

Here is the behavior:

class OpenPopupBehaviors : Behavior<UserControl>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        this.AssociatedObject.KeyDown += _KeyBoardBehaviorKeyDown;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        this.AssociatedObject.KeyDown -= _KeyBoardBehaviorKeyDown;
    }

    void _KeyBoardBehaviorKeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.F && (Keyboard.Modifiers & (ModifierKeys.Control)) == (ModifierKeys.Control))
        {

            var popup = FindPopupObject as UserManagement.Controls.NonTopmostPopup;
            if (popup == null)
                return;

            popup.IsOpen = true;
        }

        if (e.Key == Key.G && (Keyboard.Modifiers & (ModifierKeys.Control)) == (ModifierKeys.Control))
        {
            var popup = GotoPopupObject as Popup;
            if (popup == null)
                return;

            popup.IsOpen = true;
        }
    }

    public static readonly DependencyProperty FindPopupObjectProperty =
        DependencyProperty.RegisterAttached("FindPopupObject", typeof(object), typeof(OpenPopupBehaviors), new UIPropertyMetadata(null));

    public object FindPopupObject
    {
        get { return (object)GetValue(FindPopupObjectProperty); }
        set { SetValue(FindPopupObjectProperty, value); }
    }

    public static readonly DependencyProperty GotoPopupObjectProperty =
        DependencyProperty.RegisterAttached("GotoPopupObject", typeof(object), typeof(OpenPopupBehaviors), new UIPropertyMetadata(null));

    public object GotoPopupObject
    {
        get { return (object)GetValue(GotoPopupObjectProperty); }
        set { SetValue(GotoPopupObjectProperty, value); }
    }
}

Upvotes: 0

Views: 4234

Answers (1)

pushpraj
pushpraj

Reputation: 13679

So far I can see is that the focus if your issue

you can make use of Preview events to receive the events even if the focus is on control's child or their descendants

protected override void OnAttached()
{
    base.OnAttached();
    this.AssociatedObject.PreviewKeyDown += _KeyBoardBehaviorKeyDown;
}

protected override void OnDetaching()
{
    base.OnDetaching();
    this.AssociatedObject.PreviewKeyDown-= _KeyBoardBehaviorKeyDown;
}

I have changed KeyDown to PreviewKeyDown

above solution will work as long as the AssociatedObject have focus on it or any child within it. if you look forward to control it globally then perhaps you may need to attach the events to top level elements eg. Window

so in order to do that you need to find the appropriate parent of AssociatedObject and attach the event to the same.

also make sure that the following cast is valid

FindPopupObject as UserManagement.Controls.NonTopmostPopup;

it could be

FindPopupObject as Popup;

Upvotes: 1

Related Questions