Как заставить поведение взаимодействия работать с UserControl

У меня есть следующий UserControl, к которому привязано поведение. На данный момент мне нужно выбрать один из элементов DataGrid, чтобы он запустил поведение.

Только догадываюсь, но это вроде понятно, потому что эти контейнеры не могут быть сфокусированы или не должны регистрировать события клавиатуры, поэтому он переходит к следующему доступному дочернему элементу ???

Я мог бы разместить эту функцию в окне, однако этот UserControl можно заменить другим UserControl, и я предпочитаю, чтобы он не валялся. Это просто уникальный случай в моем приложении, когда единственное, что отображается в окне, - это DataGrid, и я не обязательно хочу выбирать элемент DataGrid, чтобы начать поведение.

Мой вопрос: можно ли заставить работать следующее поведение? Либо в UserControl, либо в Grid, либо, возможно, в каком-либо другом элементе управления, позволяющем это сделать.

<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>

Вот поведение:

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); }
    }
}

person Hank    schedule 02.07.2014    source источник


Ответы (1)


Пока я вижу, что если ваша проблема

вы можете использовать Preview события для получения событий, даже если фокус находится на дочернем элементе элемента управления или его потомках

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

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

Я изменил KeyDown на PreviewKeyDown

указанное выше решение будет работать до тех пор, пока AssociatedObject сфокусируется на нем или на любом его дочернем элементе. если вы с нетерпением ждете возможности контролировать его глобально, возможно, вам может потребоваться прикрепить события к элементам верхнего уровня, например. Window

поэтому для этого вам нужно найти соответствующий родительский элемент AssociatedObject и присоединить событие к нему.

также убедитесь, что следующее приведение допустимо

FindPopupObject as UserManagement.Controls.NonTopmostPopup;

возможно

FindPopupObject as Popup;
person pushpraj    schedule 02.07.2014
comment
Я также добавил Focusable = True в UserControl, чтобы посмотреть, изменилось ли это. К сожалению, когда экран загружается впервые, и я нажимаю Ctrl + f, ничего не происходит, но когда я выбираю элемент, открывается всплывающее окно. - person Hank; 02.07.2014
comment
Фокусируемый просто включите, чтобы его можно было сфокусировать. что вы можете сделать, так это установить FocusManager.FocusedElement="{Binding RelativeSource={RelativeSource Self}}" в элементе LaunchPad в главном окне. это поможет вам сосредоточить контроль. если по-прежнему не работает, прикрепите события к родительскому окну вместо пользовательского элемента управления. - person pushpraj; 02.07.2014