2

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>

MainPage.xaml.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace Focus
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{

    public static MainPage Current;
    public MyControl ctrl;

    public MainPage()
    {
        this.InitializeComponent();
        Current = this;
        ctrl = new MyControl();
        BG.Children.Add(ctrl);

        ctrl.KeyDown += ctrl_KeyDown;
        ctrl.KeyUp += ctrl_KeyUp;
    }

    void ctrl_KeyUp(object sender, KeyRoutedEventArgs e)
    {
        ShowInfo("Pressed " + e.Key);
    }

    private void ctrl_KeyDown(object sender, KeyRoutedEventArgs e)
    {
        ShowInfo("Released " + e.Key);
    }

    /// <summary>
    /// Invoked when this page is about to be displayed in a Frame.
    /// </summary>
    /// <param name="e">Event data that describes how this page was reached.  The Parameter
    /// property is typically used to configure the page.</param>
    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
    }

    public void ShowInfo(string text)
    {
        InfoText.Text = text + Environment.NewLine + InfoText.Text;
    }

    private void FocusClick(object sender, RoutedEventArgs e)
    {
        ctrl.Focus(FocusState.Programmatic);
    }
}
}

MyControl.cs

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

これは、Focus という空のプロジェクトで行います。上記の 3 つのファイルは、それぞれ MainPage.xaml、MainPage.xaml.cs、および MyControl.cs です。

4

1 に答える 1

0

あなたの例を実行しましたが、WinRT にバグがあるようです。このMSDN スレッドを読むことができます。LostFocus回避策として、コントロールのイベントにサブスクリプションを追加できます。

ctrl.LostFocus += ctrl_LostFocus;
void ctrl_LostFocus(object sender, RoutedEventArgs e)
{
    ((MyControl)sender).Focus(FocusState.Programmatic);
}

コントロールが失われるたびに手動でコントロールにフォーカスを設定します。しかし、私にとっては、あなたのコントロールが常に集中しているため、それは悪い解決策です。もちろん、このメソッドを拡張して追加のロジックを提供することもできます。

于 2012-11-15T11:52:03.473 に答える