C# 单击ContentControl不会使其成为焦点

C# 单击ContentControl不会使其成为焦点,c#,windows-8,winrt-xaml,C#,Windows 8,Winrt Xaml,我使用的是我自己的类,派生自ContentControl(我们称之为MyControl),我希望用户能够订阅我的控件的KeyDown和KeyUp事件 我遇到的问题是MyControl似乎没有接收任何关键事件。我推断这可能是一个焦点问题。例如,如果我向项目中添加一个按钮,该按钮以编程方式设置MyControl上的焦点,那么我将开始接收这些事件。问题是,只要我点击任何地方,包括我自己的控件,它似乎就会失去焦点(无论哪种方式,按键都不再工作)。我也无法通过单击将其返回,但似乎必须使用MyControl

我使用的是我自己的类,派生自ContentControl(我们称之为MyControl),我希望用户能够订阅我的控件的KeyDown和KeyUp事件

我遇到的问题是MyControl似乎没有接收任何关键事件。我推断这可能是一个焦点问题。例如,如果我向项目中添加一个按钮,该按钮以编程方式设置MyControl上的焦点,那么我将开始接收这些事件。问题是,只要我点击任何地方,包括我自己的控件,它似乎就会失去焦点(无论哪种方式,按键都不再工作)。我也无法通过单击将其返回,但似乎必须使用MyControl.Focus方法

因此,我的问题是:如何通过单击控件使其能够接受焦点


此外,为了让您享受,我在下面添加了一个小样本项目,以演示我遇到的问题:

MainPage.xaml

<Page
x:Class="Focus.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Focus"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="300"/>
    </Grid.ColumnDefinitions>
    <Grid x:Name="BG">

    </Grid>
    <StackPanel Grid.Column="1" Orientation="Vertical">
        <StackPanel Orientation="Horizontal">  
            <Button Content="Focus" Click="FocusClick"/>
        </StackPanel>
        <TextBlock x:Name="InfoText" FontSize="16" TextWrapping="Wrap" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
    </StackPanel>
</Grid>
</Page>
这是通过一个名为Focus的空白项目完成的。
上面的3个文件分别是MainPage.xaml、MainPage.xaml.cs和MyControl.cs。

我已经运行了您的示例,似乎WinRT中存在一些错误,您可以阅读此内容。作为一种解决方法,您可以向控件的
LostFocus
事件添加订阅:

ctrl.LostFocus += ctrl_LostFocus;
void ctrl_LostFocus(object sender, RoutedEventArgs e)
{
    ((MyControl)sender).Focus(FocusState.Programmatic);
}
并在每次控件丢失时手动将焦点设置为控件。
但对我来说,这是一个糟糕的解决方案,因为你的控制将永远集中。当然,您可以扩展此方法以提供一些附加逻辑。

我发现,如果我让我控制订阅PointerReleased事件,然后以编程方式将焦点设置为将工作的控件,前提是我将e.Handled设置为true。没有e,它就不能工作。我假设这是因为有一个父框架元素(默认值,甚至是MainPage的父元素),如果它获取e.handled=false的事件,它将占据焦点。是的,但如果将e.handled设置为true,则位于控件上方的可视树中的任何控件都不会接收PointerReleased事件,因此您必须记住这一点。是的。不过,它在Windows8中的工作方式似乎仍然如此。例如,如果您有一个ScrollViewer,并将其IsTabStop设置为true,则它将处理PointerReleased事件(否则不会处理)。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.UI;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Shapes;
using Windows.UI.Xaml;

namespace Focus
{
public class MyControl : ContentControl
{

    public MyControl()
        : base()
    {
        LinearGradientBrush lb = new LinearGradientBrush();
        lb.StartPoint = new Point(0, 0);
        lb.EndPoint = new Point(1, 1);
        lb.GradientStops.Add(new GradientStop() { Color = Colors.Red, Offset = 0, });
        lb.GradientStops.Add(new GradientStop() { Color = Colors.Yellow, Offset = 1, });

        Rectangle rect = new Rectangle();
        rect.Width = 800;
        rect.Height = 1000;
        rect.Fill = lb;
        this.Content = rect;
    }
}
}
ctrl.LostFocus += ctrl_LostFocus;
void ctrl_LostFocus(object sender, RoutedEventArgs e)
{
    ((MyControl)sender).Focus(FocusState.Programmatic);
}