C# 如何让交互行为在UserControl上工作

C# 如何让交互行为在UserControl上工作,c#,wpf,xaml,user-controls,attachedbehaviors,C#,Wpf,Xaml,User Controls,Attachedbehaviors,我有下面的UserControl,它有一个附加的行为。目前,我必须选择一个DataGrid项,以便它运行该行为 这里只是猜测,但这是可以理解的,因为这些容器不可聚焦或者不应该注册键盘事件,所以它会转到下一个可用的子容器 我可以把这个功能放在窗口上,但是这个UserControl可以被另一个UserControl替换掉,我更希望它不要到处乱放。 在我的应用程序中,这只是一个独特的情况,窗口上唯一的东西就是DataGrid,我不一定要选择DataGrid项来开始该行为 我的问题是:有可能让以下行为起

我有下面的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); }
    }
}
类openpopubehaviors:行为
{
受保护的覆盖无效附加()
{
base.onatached();
this.AssociatedObject.KeyDown+=\u键盘行为向下;
}
附加时受保护的覆盖无效()
{
base.OnDetaching();
this.AssociatedObject.KeyDown-=\u键盘行为向下;
}
void _KeyBoardBehaviorKeyDown(对象发送方,KeyEventArgs e)
{
如果(e.Key==Key.F&&(Keyboard.Modifiers&(ModifierKeys.Control))==(ModifierKeys.Control))
{
var popup=FindPopupObject作为UserManagement.Controls.NonTopmostPopup;
如果(弹出==null)
返回;
popup.IsOpen=true;
}
if(e.Key==Key.G&&(Keyboard.Modifiers&(ModifierKeys.Control))==(ModifierKeys.Control))
{
var popup=GotoPopupObject作为弹出窗口;
如果(弹出==null)
返回;
popup.IsOpen=true;
}
}
公共静态只读从属属性FindPopupObject属性=
DependencyProperty.RegisterAttached(“FindPopupObject”、typeof(object)、typeof(OpenPopubeHaviors)、new UIPropertyMetadata(null));
公共对象FindPopupObject
{
获取{return(object)GetValue(FindPopupObjectProperty);}
set{SetValue(FindPopupObjectProperty,value);}
}
公共静态只读DependencyProperty GotoPopupObjectProperty=
DependencyProperty.RegisterAttached(“GotoPopupObject”、typeof(object)、typeof(OpenPopubeHaviors)、new UIPropertyMetadata(null));
公共对象GotoPopupObject
{
获取{return(object)GetValue(GotoPopupObjectProperty);}
set{SetValue(GotoPopupObjectProperty,value);}
}
}

到目前为止,我能看到的是,如果您的问题

您可以使用
预览
事件来接收事件,即使焦点是控件的子级或子级

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

protected override void OnDetaching()
{
    base.OnDetaching();
    this.AssociatedObject.PreviewKeyDown-= _KeyBoardBehaviorKeyDown;
}
我已将
KeyDown
更改为
PreviewKeyDown

只要
关联对象
关注它或其中的任何子对象,上述解决方案就可以工作。如果您希望对其进行全局控制,则可能需要将事件附加到顶级元素,例如
窗口

因此,为了做到这一点,您需要找到
AssociatedObject
的适当父对象,并将事件附加到该对象

还要确保以下强制转换有效

FindPopupObject as UserManagement.Controls.NonTopmostPopup;
可能是

FindPopupObject as Popup;

我还向UserControl添加了Focusable=“True”,以查看这是否会产生影响。不幸的是,当屏幕第一次加载,我按下Ctrl+f时,什么都没有发生,但当我选择一个项目时,它会打开弹出窗口。可聚焦只是启用它可以聚焦。您可以做的是在主窗口的
LaunchPad
元素中设置
FocusManager.FocusedElement=“{Binding RelativeSource={RelativeSource Self}}”
。这将帮助你集中精力控制。如果仍然不起作用,则将事件附加到父窗口,而不是用户控件。